2 * Copyright (C) 2015-2019 "IoT.bzh"
3 * Author "Fulup Ar Foll"
4 * Author José Bollo <jose.bollo@iot.bzh>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
26 #include "afb-session.h"
27 #include "afb-context.h"
28 #include "afb-token.h"
31 #include "afb-permission-text.h"
34 static void init_context(struct afb_context *context, struct afb_session *session, struct afb_token *token, struct afb_cred *cred)
36 assert(session != NULL);
38 /* reset the context for the session */
39 context->session = session;
41 context->super = NULL;
42 context->api_key = NULL;
43 context->token = afb_token_addref(token);
44 context->credentials = afb_cred_addref(cred);
47 void afb_context_subinit(struct afb_context *context, struct afb_context *super)
49 context->session = afb_session_addref(super->session);
51 context->super = super;
52 context->api_key = NULL;
53 context->token = afb_token_addref(super->token);
54 context->credentials = afb_cred_addref(super->credentials);
57 void afb_context_init(struct afb_context *context, struct afb_session *session, struct afb_token *token, struct afb_cred *cred)
59 init_context(context, afb_session_addref(session), token, cred);
62 int afb_context_connect(struct afb_context *context, const char *uuid, struct afb_token *token, struct afb_cred *cred)
65 struct afb_session *session;
67 session = afb_session_get (uuid, AFB_SESSION_TIMEOUT_DEFAULT, &created);
70 init_context(context, session, token, cred);
77 int afb_context_connect_validated(struct afb_context *context, const char *uuid, struct afb_token *token, struct afb_cred *cred)
79 int rc = afb_context_connect(context, uuid, token, cred);
81 context->validated = 1;
85 void afb_context_init_validated(struct afb_context *context, struct afb_session *session, struct afb_token *token, struct afb_cred *cred)
87 afb_context_init(context, session, token, cred);
88 context->validated = 1;
91 void afb_context_disconnect(struct afb_context *context)
93 if (context->session && !context->super && context->closing && !context->closed) {
94 afb_context_change_loa(context, 0);
95 afb_context_set(context, NULL, NULL);
98 afb_session_unref(context->session);
99 context->session = NULL;
100 afb_cred_unref(context->credentials);
101 context->credentials = NULL;
102 afb_token_unref(context->token);
103 context->token = NULL;
106 void afb_context_change_cred(struct afb_context *context, struct afb_cred *cred)
108 struct afb_cred *ocred = context->credentials;
110 context->credentials = afb_cred_addref(cred);
111 afb_cred_unref(ocred);
115 void afb_context_change_token(struct afb_context *context, struct afb_token *token)
117 struct afb_token *otoken = context->token;
118 if (otoken != token) {
119 context->token = afb_token_addref(token);
120 afb_token_unref(otoken);
124 const char *afb_context_on_behalf_export(struct afb_context *context)
126 return context->credentials ? afb_cred_export(context->credentials) : NULL;
129 int afb_context_on_behalf_import(struct afb_context *context, const char *exported)
132 struct afb_cred *imported, *ocred;
134 if (!exported || !*exported)
137 if (afb_context_has_permission(context, afb_permission_on_behalf_credential)) {
138 imported = afb_cred_import(exported);
140 ERROR("Can't import on behalf credentials: %m");
143 ocred = context->credentials;
144 context->credentials = imported;
145 afb_cred_unref(ocred);
149 ERROR("On behalf credentials refused");
156 void afb_context_on_behalf_other_context(struct afb_context *context, struct afb_context *other)
158 afb_context_change_cred(context, other->credentials);
159 afb_context_change_token(context, other->token);
162 int afb_context_has_permission(struct afb_context *context, const char *permission)
164 return afb_perm_check(context, permission);
167 void afb_context_has_permission_async(
168 struct afb_context *context,
169 const char *permission,
170 void (*callback)(void *_closure, int _status),
174 return afb_perm_check_async(context, permission, callback, closure);
177 const char *afb_context_uuid(struct afb_context *context)
179 return context->session ? afb_session_uuid(context->session) : NULL;
182 void *afb_context_make(struct afb_context *context, int replace, void *(*make_value)(void *closure), void (*free_value)(void *item), void *closure)
184 assert(context->session != NULL);
185 return afb_session_cookie(context->session, context->api_key, make_value, free_value, closure, replace);
188 void *afb_context_get(struct afb_context *context)
190 assert(context->session != NULL);
191 return afb_session_get_cookie(context->session, context->api_key);
194 int afb_context_set(struct afb_context *context, void *value, void (*free_value)(void*))
196 assert(context->session != NULL);
197 return afb_session_set_cookie(context->session, context->api_key, value, free_value);
200 void afb_context_close(struct afb_context *context)
202 context->closing = 1;
206 struct afb_context *context;
207 void (*callback)(void *_closure, int _status);
211 static void check_context_cb(void *closure_chkctx, int status)
213 struct chkctx *cc = closure_chkctx;
214 struct afb_context *context = cc->context;
215 void (*callback)(void*,int) = cc->callback;
216 void *closure = cc->closure;
220 context->validated = 1;
222 context->invalidated = 1;
223 callback(closure, status);
226 static int check_context(
227 struct afb_context *context,
228 void (*callback)(void *_closure, int _status),
234 if (context->validated)
236 else if (context->invalidated)
240 r = check_context(context->super, callback, closure);
242 r = afb_context_has_permission(context, afb_permission_token_valid);
244 cc = malloc(sizeof *cc);
246 cc->context = context;
247 cc->callback = callback;
248 cc->closure = closure;
249 afb_context_has_permission_async(context, afb_permission_token_valid, check_context_cb, cc);
252 ERROR("out-of-memory");
256 context->validated = 1;
258 context->invalidated = 1;
263 int afb_context_check(struct afb_context *context)
265 return check_context(context, 0, 0);
268 void afb_context_check_async(
269 struct afb_context *context,
270 void (*callback)(void *_closure, int _status),
273 int r = check_context(context, callback, closure);
275 callback(closure, r);
278 static inline const void *loa_key(struct afb_context *context)
280 return (const void*)(1+(intptr_t)(context->api_key));
283 static inline void *loa2ptr(unsigned loa)
285 return (void*)(intptr_t)loa;
288 static inline unsigned ptr2loa(void *ptr)
290 return (unsigned)(intptr_t)ptr;
293 int afb_context_change_loa(struct afb_context *context, unsigned loa)
299 if (!afb_context_check(context)) {
304 return afb_session_set_cookie(context->session, loa_key(context), loa2ptr(loa), NULL);
307 unsigned afb_context_get_loa(struct afb_context *context)
309 assert(context->session != NULL);
310 return ptr2loa(afb_session_get_cookie(context->session, loa_key(context)));
313 int afb_context_check_loa(struct afb_context *context, unsigned loa)
315 return afb_context_get_loa(context) >= loa;