JSON.pm 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package Trog::Routes::JSON;
  2. use strict;
  3. use warnings;
  4. no warnings 'experimental';
  5. use feature qw{signatures state};
  6. use Clone qw{clone};
  7. use JSON::MaybeXS();
  8. use Trog::Config();
  9. use Trog::Auth();
  10. use Trog::Routes::HTML();
  11. my $conf = Trog::Config::get();
  12. # TODO de-duplicate this, it's shared in html
  13. my $theme_dir = '';
  14. $theme_dir = "themes/" . $conf->param('general.theme') if $conf->param('general.theme') && -d "www/themes/" . $conf->param('general.theme');
  15. our %routes = (
  16. '/api/catalog' => {
  17. method => 'GET',
  18. callback => \&catalog,
  19. parameters => [],
  20. },
  21. '/api/webmanifest' => {
  22. method => 'GET',
  23. callback => \&webmanifest,
  24. parameters => [],
  25. },
  26. '/api/version' => {
  27. method => 'GET',
  28. callback => \&version,
  29. parameters => [],
  30. },
  31. '/api/auth_change_request/(.*)' => {
  32. method => 'GET',
  33. callback => \&process_auth_change_request,
  34. captures => ['token'],
  35. noindex => 1,
  36. robot_name => '/api/auth_change_request/*',
  37. },
  38. );
  39. # Clone / redact for catalog
  40. my $cloned = clone( \%routes );
  41. foreach my $r ( keys(%$cloned) ) {
  42. delete $cloned->{$r}{callback};
  43. }
  44. my $enc = JSON::MaybeXS->new( utf8 => 1 );
  45. # Note to authors, don't forget to update this
  46. sub _version () {
  47. return '1.0';
  48. }
  49. # Special case of a non data-structure JSON return
  50. sub version ($query) {
  51. state $ret = [ 200, [ 'Content-type' => "application/json", ETag => 'version-' . _version() ], [ _version() ] ];
  52. return $ret;
  53. }
  54. sub catalog ($query) {
  55. return _render( 200, { ETag => 'catalog-' . _version() }, %$cloned );
  56. }
  57. sub webmanifest ($query) {
  58. state $headers = { ETag => 'manifest-' . _version() };
  59. state %manifest = (
  60. "icons" => [
  61. { "src" => "$theme_dir/img/icon/favicon-32.png", "type" => "image/png", "sizes" => "32x32" },
  62. { "src" => "$theme_dir/img/icon/favicon-48.png", "type" => "image/png", "sizes" => "48x48" },
  63. { "src" => "$theme_dir/img/icon/favicon-167.png", "type" => "image/png", "sizes" => "167x167" },
  64. { "src" => "$theme_dir/img/icon/favicon-180.png", "type" => "image/png", "sizes" => "180x180" },
  65. { "src" => "$theme_dir/img/icon/favicon-192.png", "type" => "image/png", "sizes" => "192x192" },
  66. { "src" => "$theme_dir/img/icon/favicon-512.png", "type" => "image/png", "sizes" => "512x512" },
  67. ],
  68. );
  69. return _render( 200, $headers, %manifest );
  70. }
  71. sub process_auth_change_request ($query) {
  72. my $token = $query->{token};
  73. my $msg = Trog::Auth::process_change_request($token);
  74. return Trog::Routes::HTML::forbidden($query) unless $msg;
  75. return _render(
  76. 200, undef,
  77. message => $msg,
  78. result => 'success',
  79. );
  80. }
  81. sub _render ( $code, $headers, %data ) {
  82. return Trog::Renderer->render(
  83. code => 200,
  84. data => \%data,
  85. template => 'bogus.tx',
  86. contenttype => 'application/json',
  87. headers => $headers,
  88. );
  89. }
  90. 1;