blob: 209b8cb7e2e5bdfffe9a8e7ef4e875ec29e749aa [file] [log] [blame]
Akron80027d12016-01-20 17:36:36 +01001package Kalamar::Plugin::KalamarUser;
2use Mojo::Base 'Mojolicious::Plugin';
3use Mojo::ByteStream 'b';
4
5has 'api';
Akrondadacf12016-01-22 19:24:59 +01006has 'ua';
Akron80027d12016-01-20 17:36:36 +01007
8sub register {
9 my ($plugin, $mojo, $param) = @_;
10
11 # Load parameter from config file
12 if (my $config_param = $mojo->config('Kalamar')) {
13 $param = { %$param, %$config_param };
14 };
15
Akron2cb9a3d2016-02-09 23:59:46 +010016 # Load 'notifications' plugin
17 unless (exists $mojo->renderer->helpers->{notify}) {
18 $mojo->plugin(Notifications => {
19 HTML => 1
20 });
21 };
22
Akron80027d12016-01-20 17:36:36 +010023 # Set API!
24 $plugin->api($param->{api}) or return;
Akrondadacf12016-01-22 19:24:59 +010025 $plugin->ua(Mojo::UserAgent->new);
Akron80027d12016-01-20 17:36:36 +010026
27 # Get the user token necessary for authorization
28 $mojo->helper(
29 'user_auth' => sub {
30 my $c = shift;
31
32 # Get token from stash
33 my $token = $c->stash('auth');
34 return $token if $token;
35
36 # Set token to stash
37 $c->stash(auth => $c->session('auth'));
38 return $c->stash('auth');
39 }
40 );
41
42 # Login
43 $mojo->helper(
44 'user.login' => sub {
45 my $c = shift;
46 my ($user, $pwd) = @_;
47
Akrondadacf12016-01-22 19:24:59 +010048 return if (index($user, ':') >= 0);
Akron80027d12016-01-20 17:36:36 +010049
50 my $url = Mojo::URL->new($plugin->api)->path('auth/apiToken');
51 my $tx = $c->ua->get($url => {
52 Authorization => 'Basic ' . b($user . ':' . $pwd)->b64_encode
53 });
54
55 # Login successful
56 if (my $res = $tx->success) {
57 my $jwt = $res->json;
58
59 my $auth = $jwt->{token_type} . ' ' . $jwt->{token};
60
61 $mojo->log->debug(qq!Login successful: "$user" with "$auth"!);
62
63 # Set session info
64 $c->session(user => $user);
65 $c->session(auth => $auth);
66
67 $c->stash(user => $user);
68 $c->stash(auth => $auth);
69
70 # Set cache
71 $c->chi('user')->set($auth => $user);
72 return 1;
Akron2cb9a3d2016-02-09 23:59:46 +010073 }
74
75 elsif (my $e = $tx->error) {
76 $c->notify(
77 error =>
78 ($e->{code} ? $e->{code} . ': ' : '') .
79 $e->{message} . ' for Login (remote)'
80 );
Akron80027d12016-01-20 17:36:36 +010081 };
82
83 $mojo->log->debug(qq!Login fail: "$user"!);
84
85 return;
86 }
87 );
88
89 # Get details, settings etc. with authorization
90 $mojo->helper(
91 'user.get' => sub {
92 my $c = shift;
93 my $param = shift;
94
Akrondadacf12016-01-22 19:24:59 +010095 return unless $param =~ m/^details|settings$/;
Akron80027d12016-01-20 17:36:36 +010096
97 # The user may be logged in
98 my $auth = ($c->stash('auth') || $c->session('auth')) or return;
99
100 # Get namespaced cache
101 my $chi = $c->chi('user');
102
103 # Get user and check, if the user is real
104 my $user = $chi->get($auth);
105
106 # Check if the user is really logged in
107 my $value = $chi->get($user . '_' . $param);
108
109 unless ($value) {
Akrondadacf12016-01-22 19:24:59 +0100110
111 my $tx = $plugin->build_authorized_tx($auth, 'GET', 'user/' . $param);
112 $tx = $plugin->ua->start($tx);
113 unless ($value = $tx->success) {
114# warn $tx->code;
115 return;
116 }
117# else {
118# warn $c->dumper($value->json);
119# };
120 $value = $value->json;
121
Akron80027d12016-01-20 17:36:36 +0100122 $chi->set($user . '_' . $param => $value);
123 };
124
125 # Return value
126 return $value;
127 }
128 );
129
130
131 # Logout
132 $mojo->helper(
133 'user.logout' => sub {
134 my $c = shift;
135
136 # TODO: csrf-protection!
137 # TODO: REVOKE ON THE SERVER ONCE SUPPORTED!
138
139 # Clear cache
140 $c->chi('user')->remove($c->user_auth);
141
142 # Expire session
143 $c->session(expires => 1);
144 return $c->redirect_to('index');
145 }
146 );
147};
148
Akrondadacf12016-01-22 19:24:59 +0100149sub build_authorized_tx {
Akron80027d12016-01-20 17:36:36 +0100150 my $plugin = shift;
151
Akrondadacf12016-01-22 19:24:59 +0100152 my $ua = $plugin->ua;
153 my ($auth, $method, $path, @values) = @_;
154
155 my $header;
156 if (@values && ref $values[0] eq 'HASH') {
157 $header = shift @values;
158 }
159 else {
160 $header = {};
161 };
162
Akron80027d12016-01-20 17:36:36 +0100163 my $url = Mojo::URL->new($plugin->api)->path($path);
164
Akrondadacf12016-01-22 19:24:59 +0100165 $header->{Authorization} = $auth;
Akron80027d12016-01-20 17:36:36 +0100166
Akrondadacf12016-01-22 19:24:59 +0100167 return $ua->build_tx($method, $url => $header => @values);
Akron80027d12016-01-20 17:36:36 +0100168};
169
170
1711;
172
173
174__END__
Akrondadacf12016-01-22 19:24:59 +0100175
176# Failure
177entity {
178 "errors":[
179 [204,"authentication token is expired","eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0MSIsImlzcyI6Imh0dHA6IiwiZXhwIjoxNDUyOTY2NzAxOTYxfQ.W_rJjJ8i82Srw7MiSPRGeIBLE-rMPmSPK9BA7Dt_7Yc"]
180 ]
181}
182