use crate::oauth::{OAuthClient, OAuthConfig};
use crate::session::{SecureStorage, Token};
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
use std::ptr;
use std::sync::Arc;
pub struct SchlusselClient {
_private: [u8; 0],
}
pub struct SchlusselToken {
_private: [u8; 0],
}
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum SchlusselError {
Ok = 0,
InvalidParameter = 1,
StorageError = 2,
HttpError = 3,
AuthorizationDenied = 4,
TokenExpired = 5,
NoRefreshToken = 6,
UnknownError = 99,
}
#[no_mangle]
pub unsafe extern "C" fn schlussel_client_new_github(
client_id: *const c_char,
scopes: *const c_char,
app_name: *const c_char,
) -> *mut SchlusselClient {
if client_id.is_null() || app_name.is_null() {
return ptr::null_mut();
}
let client_id_str = match CStr::from_ptr(client_id).to_str() {
Ok(s) => s,
Err(_) => return ptr::null_mut(),
};
let app_name_str = match CStr::from_ptr(app_name).to_str() {
Ok(s) => s,
Err(_) => return ptr::null_mut(),
};
let scopes_opt = if scopes.is_null() {
None
} else {
CStr::from_ptr(scopes).to_str().ok()
};
let storage = match SecureStorage::new(app_name_str) {
Ok(s) => Arc::new(s),
Err(_) => return ptr::null_mut(),
};
let config = OAuthConfig::github(client_id_str, scopes_opt);
let client = Arc::new(OAuthClient::new(config, storage));
Box::into_raw(Box::new(client)) as *mut SchlusselClient
}
#[no_mangle]
pub unsafe extern "C" fn schlussel_authorize_device(
client: *mut SchlusselClient,
) -> *mut SchlusselToken {
if client.is_null() {
return ptr::null_mut();
}
let client_ref = &*(client as *const Arc<OAuthClient<SecureStorage>>);
match client_ref.authorize_device() {
Ok(token) => Box::into_raw(Box::new(token)) as *mut SchlusselToken,
Err(_) => ptr::null_mut(),
}
}
#[no_mangle]
pub unsafe extern "C" fn schlussel_save_token(
client: *mut SchlusselClient,
key: *const c_char,
token: *mut SchlusselToken,
) -> SchlusselError {
if client.is_null() || key.is_null() || token.is_null() {
return SchlusselError::InvalidParameter;
}
let client_ref = &*(client as *const Arc<OAuthClient<SecureStorage>>);
let token_ref = &*(token as *const Token);
let key_str = match CStr::from_ptr(key).to_str() {
Ok(s) => s,
Err(_) => return SchlusselError::InvalidParameter,
};
match client_ref.save_token(key_str, token_ref.clone()) {
Ok(_) => SchlusselError::Ok,
Err(_) => SchlusselError::StorageError,
}
}
#[no_mangle]
pub unsafe extern "C" fn schlussel_token_get_access_token(
token: *mut SchlusselToken,
) -> *mut c_char {
if token.is_null() {
return ptr::null_mut();
}
let token_ref = &*(token as *const Token);
match CString::new(token_ref.access_token.clone()) {
Ok(s) => s.into_raw(),
Err(_) => ptr::null_mut(),
}
}
#[no_mangle]
pub unsafe extern "C" fn schlussel_token_is_expired(token: *mut SchlusselToken) -> i32 {
if token.is_null() {
return 0;
}
let token_ref = &*(token as *const Token);
if token_ref.is_expired() {
1
} else {
0
}
}
#[no_mangle]
pub unsafe extern "C" fn schlussel_string_free(s: *mut c_char) {
if !s.is_null() {
drop(CString::from_raw(s));
}
}
#[no_mangle]
pub unsafe extern "C" fn schlussel_token_free(token: *mut SchlusselToken) {
if !token.is_null() {
drop(Box::from_raw(token as *mut Token));
}
}
#[no_mangle]
pub unsafe extern "C" fn schlussel_client_free(client: *mut SchlusselClient) {
if !client.is_null() {
drop(Box::from_raw(
client as *mut Arc<OAuthClient<SecureStorage>>,
));
}
}