Skip to main content

ri/java/classes/
auth.rs

1//! Copyright © 2025-2026 Wenze Wei. All Rights Reserved.
2//!
3//! This file is part of Ri.
4//! The Ri project belongs to the Dunimd Team.
5//!
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
9//!
10//!     http://www.apache.org/licenses/LICENSE-2.0
11//!
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.
17
18//! # Auth Module JNI Bindings
19//!
20//! JNI bindings for Ri auth classes.
21
22use crate::auth::{
23    RiAuthConfig, RiAuthModule, RiJWTClaims, RiJWTManager, RiJWTRevocationList,
24    RiJWTValidationOptions, RiOAuthManager, RiOAuthProvider, RiOAuthToken, RiOAuthUserInfo,
25    RiPermission, RiPermissionManager, RiRevokedTokenInfo, RiRole, RiSecurityManager, RiSession,
26    RiSessionManager,
27};
28use crate::java::exception::check_not_null;
29use jni::objects::{JClass, JObjectArray, JString};
30use jni::sys::{jboolean, jint, jlong, jobjectArray, jstring};
31use jni::JNIEnv;
32use std::collections::HashSet;
33
34// =============================================================================
35// RiAuthConfig JNI Bindings
36// =============================================================================
37
38#[no_mangle]
39pub extern "system" fn Java_com_dunimd_ri_auth_RiAuthConfig_new0(
40    _env: JNIEnv,
41    _class: JClass,
42) -> jlong {
43    let config = Box::new(RiAuthConfig::default());
44    Box::into_raw(config) as jlong
45}
46
47#[no_mangle]
48pub extern "system" fn Java_com_dunimd_ri_auth_RiAuthConfig_free0(
49    _env: JNIEnv,
50    _class: JClass,
51    ptr: jlong,
52) {
53    if ptr != 0 {
54        unsafe {
55            let _ = Box::from_raw(ptr as *mut RiAuthConfig);
56        }
57    }
58}
59
60// =============================================================================
61// RiAuthModule JNI Bindings
62// =============================================================================
63
64#[no_mangle]
65pub extern "system" fn Java_com_dunimd_ri_auth_RiAuthModule_new0(
66    mut env: JNIEnv,
67    _class: JClass,
68    config_ptr: jlong,
69) -> jlong {
70    if !check_not_null(&mut env, config_ptr, "RiAuthConfig") {
71        return 0;
72    }
73
74    let config = unsafe { &*(config_ptr as *const RiAuthConfig) };
75    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
76    match rt.block_on(async { RiAuthModule::new(config.clone()).await }) {
77        Ok(module) => Box::into_raw(Box::new(module)) as jlong,
78        Err(_) => 0,
79    }
80}
81
82#[no_mangle]
83pub extern "system" fn Java_com_dunimd_ri_auth_RiAuthModule_free0(
84    _env: JNIEnv,
85    _class: JClass,
86    ptr: jlong,
87) {
88    if ptr != 0 {
89        unsafe {
90            let _ = Box::from_raw(ptr as *mut RiAuthModule);
91        }
92    }
93}
94
95// =============================================================================
96// RiJWTClaims JNI Bindings
97// =============================================================================
98
99#[no_mangle]
100pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTClaims_new0(
101    mut env: JNIEnv,
102    _class: JClass,
103    sub: JString,
104    roles: JObjectArray,
105    permissions: JObjectArray,
106) -> jlong {
107    let sub_str: String = env.get_string(&sub).expect("Failed to get sub").into();
108
109    let roles_len = env
110        .get_array_length(&roles)
111        .expect("Failed to get roles length");
112    let mut roles_vec = Vec::with_capacity(roles_len as usize);
113    for i in 0..roles_len {
114        if let Ok(Some(elem)) = env.get_object_array_element(&roles, i) {
115            let role_str: String = env
116                .get_string(&JString::from(elem))
117                .expect("Failed to get role")
118                .into();
119            roles_vec.push(role_str);
120        }
121    }
122
123    let perms_len = env
124        .get_array_length(&permissions)
125        .expect("Failed to get permissions length");
126    let mut perms_vec = Vec::with_capacity(perms_len as usize);
127    for i in 0..perms_len {
128        if let Ok(Some(elem)) = env.get_object_array_element(&permissions, i) {
129            let perm_str: String = env
130                .get_string(&JString::from(elem))
131                .expect("Failed to get permission")
132                .into();
133            perms_vec.push(perm_str);
134        }
135    }
136
137    let now = std::time::SystemTime::now()
138        .duration_since(std::time::UNIX_EPOCH)
139        .expect("System time error")
140        .as_secs();
141
142    let claims = Box::new(RiJWTClaims {
143        sub: sub_str,
144        exp: now + 3600,
145        iat: now,
146        roles: roles_vec,
147        permissions: perms_vec,
148    });
149    Box::into_raw(claims) as jlong
150}
151
152#[no_mangle]
153pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTClaims_getSub0(
154    mut env: JNIEnv,
155    _class: JClass,
156    ptr: jlong,
157) -> jstring {
158    if !check_not_null(&mut env, ptr, "RiJWTClaims") {
159        return std::ptr::null_mut();
160    }
161
162    let claims = unsafe { &*(ptr as *const RiJWTClaims) };
163    env.new_string(&claims.sub)
164        .expect("Failed to create string")
165        .into_raw()
166}
167
168#[no_mangle]
169pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTClaims_getExp0(
170    mut env: JNIEnv,
171    _class: JClass,
172    ptr: jlong,
173) -> jlong {
174    if !check_not_null(&mut env, ptr, "RiJWTClaims") {
175        return 0;
176    }
177
178    let claims = unsafe { &*(ptr as *const RiJWTClaims) };
179    claims.exp as jlong
180}
181
182#[no_mangle]
183pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTClaims_getIat0(
184    mut env: JNIEnv,
185    _class: JClass,
186    ptr: jlong,
187) -> jlong {
188    if !check_not_null(&mut env, ptr, "RiJWTClaims") {
189        return 0;
190    }
191
192    let claims = unsafe { &*(ptr as *const RiJWTClaims) };
193    claims.iat as jlong
194}
195
196#[no_mangle]
197pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTClaims_getRoles0(
198    mut env: JNIEnv,
199    _class: JClass,
200    ptr: jlong,
201) -> jobjectArray {
202    if !check_not_null(&mut env, ptr, "RiJWTClaims") {
203        return std::ptr::null_mut();
204    }
205
206    let claims = unsafe { &*(ptr as *const RiJWTClaims) };
207    let roles: Vec<String> = claims.roles.clone();
208
209    let string_class = env
210        .find_class("java/lang/String")
211        .expect("Failed to find String class");
212    let array = env
213        .new_object_array(roles.len() as jint, string_class, std::ptr::null_mut())
214        .expect("Failed to create array");
215
216    for (i, role) in roles.iter().enumerate() {
217        let jstr = env.new_string(role).expect("Failed to create string");
218        env.set_object_array_element(&array, i as jint, jstr)
219            .expect("Failed to set array element");
220    }
221
222    array.into_raw()
223}
224
225#[no_mangle]
226pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTClaims_getPermissions0(
227    mut env: JNIEnv,
228    _class: JClass,
229    ptr: jlong,
230) -> jobjectArray {
231    if !check_not_null(&mut env, ptr, "RiJWTClaims") {
232        return std::ptr::null_mut();
233    }
234
235    let claims = unsafe { &*(ptr as *const RiJWTClaims) };
236    let perms: Vec<String> = claims.permissions.clone();
237
238    let string_class = env
239        .find_class("java/lang/String")
240        .expect("Failed to find String class");
241    let array = env
242        .new_object_array(perms.len() as jint, string_class, std::ptr::null_mut())
243        .expect("Failed to create array");
244
245    for (i, perm) in perms.iter().enumerate() {
246        let jstr = env.new_string(perm).expect("Failed to create string");
247        env.set_object_array_element(&array, i as jint, jstr)
248            .expect("Failed to set array element");
249    }
250
251    array.into_raw()
252}
253
254#[no_mangle]
255pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTClaims_free0(
256    _env: JNIEnv,
257    _class: JClass,
258    ptr: jlong,
259) {
260    if ptr != 0 {
261        unsafe {
262            let _ = Box::from_raw(ptr as *mut RiJWTClaims);
263        }
264    }
265}
266
267// =============================================================================
268// RiJWTValidationOptions JNI Bindings
269// =============================================================================
270
271#[no_mangle]
272pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTValidationOptions_new0(
273    _env: JNIEnv,
274    _class: JClass,
275) -> jlong {
276    let options = Box::new(RiJWTValidationOptions::default());
277    Box::into_raw(options) as jlong
278}
279
280#[no_mangle]
281pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTValidationOptions_isValidateExp0(
282    mut env: JNIEnv,
283    _class: JClass,
284    ptr: jlong,
285) -> jboolean {
286    if !check_not_null(&mut env, ptr, "RiJWTValidationOptions") {
287        return 0;
288    }
289
290    let options = unsafe { &*(ptr as *const RiJWTValidationOptions) };
291    if options.validate_exp {
292        1
293    } else {
294        0
295    }
296}
297
298#[no_mangle]
299pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTValidationOptions_setValidateExp0(
300    mut env: JNIEnv,
301    _class: JClass,
302    ptr: jlong,
303    validate: jboolean,
304) {
305    if !check_not_null(&mut env, ptr, "RiJWTValidationOptions") {
306        return;
307    }
308
309    let options = unsafe { &mut *(ptr as *mut RiJWTValidationOptions) };
310    options.validate_exp = validate != 0;
311}
312
313#[no_mangle]
314pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTValidationOptions_isValidateIat0(
315    mut env: JNIEnv,
316    _class: JClass,
317    ptr: jlong,
318) -> jboolean {
319    if !check_not_null(&mut env, ptr, "RiJWTValidationOptions") {
320        return 0;
321    }
322
323    let options = unsafe { &*(ptr as *const RiJWTValidationOptions) };
324    if options.validate_iat {
325        1
326    } else {
327        0
328    }
329}
330
331#[no_mangle]
332pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTValidationOptions_setValidateIat0(
333    mut env: JNIEnv,
334    _class: JClass,
335    ptr: jlong,
336    validate: jboolean,
337) {
338    if !check_not_null(&mut env, ptr, "RiJWTValidationOptions") {
339        return;
340    }
341
342    let options = unsafe { &mut *(ptr as *mut RiJWTValidationOptions) };
343    options.validate_iat = validate != 0;
344}
345
346#[no_mangle]
347pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTValidationOptions_getRequiredRoles0(
348    mut env: JNIEnv,
349    _class: JClass,
350    ptr: jlong,
351) -> jobjectArray {
352    if !check_not_null(&mut env, ptr, "RiJWTValidationOptions") {
353        return std::ptr::null_mut();
354    }
355
356    let options = unsafe { &*(ptr as *const RiJWTValidationOptions) };
357    let roles: Vec<String> = options.required_roles.clone();
358
359    let string_class = env
360        .find_class("java/lang/String")
361        .expect("Failed to find String class");
362    let array = env
363        .new_object_array(roles.len() as jint, string_class, std::ptr::null_mut())
364        .expect("Failed to create array");
365
366    for (i, role) in roles.iter().enumerate() {
367        let jstr = env.new_string(role).expect("Failed to create string");
368        env.set_object_array_element(&array, i as jint, jstr)
369            .expect("Failed to set array element");
370    }
371
372    array.into_raw()
373}
374
375#[no_mangle]
376pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTValidationOptions_setRequiredRoles0(
377    mut env: JNIEnv,
378    _class: JClass,
379    ptr: jlong,
380    roles: JObjectArray,
381) {
382    if !check_not_null(&mut env, ptr, "RiJWTValidationOptions") {
383        return;
384    }
385
386    let options = unsafe { &mut *(ptr as *mut RiJWTValidationOptions) };
387    let roles_len = env
388        .get_array_length(&roles)
389        .expect("Failed to get roles length");
390    let mut roles_vec = Vec::with_capacity(roles_len as usize);
391    for i in 0..roles_len {
392        if let Ok(Some(elem)) = env.get_object_array_element(&roles, i) {
393            let role_str: String = env
394                .get_string(&JString::from(elem))
395                .expect("Failed to get role")
396                .into();
397            roles_vec.push(role_str);
398        }
399    }
400    options.required_roles = roles_vec;
401}
402
403#[no_mangle]
404pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTValidationOptions_getRequiredPermissions0(
405    mut env: JNIEnv,
406    _class: JClass,
407    ptr: jlong,
408) -> jobjectArray {
409    if !check_not_null(&mut env, ptr, "RiJWTValidationOptions") {
410        return std::ptr::null_mut();
411    }
412
413    let options = unsafe { &*(ptr as *const RiJWTValidationOptions) };
414    let perms: Vec<String> = options.required_permissions.clone();
415
416    let string_class = env
417        .find_class("java/lang/String")
418        .expect("Failed to find String class");
419    let array = env
420        .new_object_array(perms.len() as jint, string_class, std::ptr::null_mut())
421        .expect("Failed to create array");
422
423    for (i, perm) in perms.iter().enumerate() {
424        let jstr = env.new_string(perm).expect("Failed to create string");
425        env.set_object_array_element(&array, i as jint, jstr)
426            .expect("Failed to set array element");
427    }
428
429    array.into_raw()
430}
431
432#[no_mangle]
433pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTValidationOptions_setRequiredPermissions0(
434    mut env: JNIEnv,
435    _class: JClass,
436    ptr: jlong,
437    permissions: JObjectArray,
438) {
439    if !check_not_null(&mut env, ptr, "RiJWTValidationOptions") {
440        return;
441    }
442
443    let options = unsafe { &mut *(ptr as *mut RiJWTValidationOptions) };
444    let perms_len = env
445        .get_array_length(&permissions)
446        .expect("Failed to get permissions length");
447    let mut perms_vec = Vec::with_capacity(perms_len as usize);
448    for i in 0..perms_len {
449        if let Ok(Some(elem)) = env.get_object_array_element(&permissions, i) {
450            let perm_str: String = env
451                .get_string(&JString::from(elem))
452                .expect("Failed to get permission")
453                .into();
454            perms_vec.push(perm_str);
455        }
456    }
457    options.required_permissions = perms_vec;
458}
459
460#[no_mangle]
461pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTValidationOptions_free0(
462    _env: JNIEnv,
463    _class: JClass,
464    ptr: jlong,
465) {
466    if ptr != 0 {
467        unsafe {
468            let _ = Box::from_raw(ptr as *mut RiJWTValidationOptions);
469        }
470    }
471}
472
473// =============================================================================
474// RiJWTManager JNI Bindings
475// =============================================================================
476
477#[no_mangle]
478pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTManager_generateToken0(
479    mut env: JNIEnv,
480    _class: JClass,
481    ptr: jlong,
482    claims_ptr: jlong,
483) -> jstring {
484    if !check_not_null(&mut env, ptr, "RiJWTManager") {
485        return std::ptr::null_mut();
486    }
487    if !check_not_null(&mut env, claims_ptr, "RiJWTClaims") {
488        return std::ptr::null_mut();
489    }
490
491    let manager = unsafe { &*(ptr as *const RiJWTManager) };
492    let claims = unsafe { &*(claims_ptr as *const RiJWTClaims) };
493
494    match manager.generate_token(
495        &claims.sub,
496        claims.roles.clone(),
497        claims.permissions.clone(),
498    ) {
499        Ok(token) => env
500            .new_string(&token)
501            .expect("Failed to create string")
502            .into_raw(),
503        Err(_) => std::ptr::null_mut(),
504    }
505}
506
507#[no_mangle]
508pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTManager_validateToken0(
509    mut env: JNIEnv,
510    _class: JClass,
511    ptr: jlong,
512    token: JString,
513) -> jlong {
514    if !check_not_null(&mut env, ptr, "RiJWTManager") {
515        return 0;
516    }
517
518    let manager = unsafe { &*(ptr as *const RiJWTManager) };
519    let token_str: String = env.get_string(&token).expect("Failed to get token").into();
520
521    match manager.validate_token(&token_str) {
522        Ok(claims) => {
523            let claims_box = Box::new(claims);
524            Box::into_raw(claims_box) as jlong
525        }
526        Err(_) => 0,
527    }
528}
529
530// =============================================================================
531// RiSession JNI Bindings
532// =============================================================================
533
534#[no_mangle]
535pub extern "system" fn Java_com_dunimd_ri_auth_RiSession_getId0(
536    mut env: JNIEnv,
537    _class: JClass,
538    ptr: jlong,
539) -> jstring {
540    if !check_not_null(&mut env, ptr, "RiSession") {
541        return std::ptr::null_mut();
542    }
543
544    let session = unsafe { &*(ptr as *const RiSession) };
545    env.new_string(&session.id)
546        .expect("Failed to create string")
547        .into_raw()
548}
549
550#[no_mangle]
551pub extern "system" fn Java_com_dunimd_ri_auth_RiSession_getUserId0(
552    mut env: JNIEnv,
553    _class: JClass,
554    ptr: jlong,
555) -> jstring {
556    if !check_not_null(&mut env, ptr, "RiSession") {
557        return std::ptr::null_mut();
558    }
559
560    let session = unsafe { &*(ptr as *const RiSession) };
561    env.new_string(&session.user_id)
562        .expect("Failed to create string")
563        .into_raw()
564}
565
566#[no_mangle]
567pub extern "system" fn Java_com_dunimd_ri_auth_RiSession_getCreatedAt0(
568    mut env: JNIEnv,
569    _class: JClass,
570    ptr: jlong,
571) -> jlong {
572    if !check_not_null(&mut env, ptr, "RiSession") {
573        return 0;
574    }
575
576    let session = unsafe { &*(ptr as *const RiSession) };
577    session.created_at as jlong
578}
579
580#[no_mangle]
581pub extern "system" fn Java_com_dunimd_ri_auth_RiSession_getLastAccessed0(
582    mut env: JNIEnv,
583    _class: JClass,
584    ptr: jlong,
585) -> jlong {
586    if !check_not_null(&mut env, ptr, "RiSession") {
587        return 0;
588    }
589
590    let session = unsafe { &*(ptr as *const RiSession) };
591    session.last_accessed as jlong
592}
593
594#[no_mangle]
595pub extern "system" fn Java_com_dunimd_ri_auth_RiSession_getExpiresAt0(
596    mut env: JNIEnv,
597    _class: JClass,
598    ptr: jlong,
599) -> jlong {
600    if !check_not_null(&mut env, ptr, "RiSession") {
601        return 0;
602    }
603
604    let session = unsafe { &*(ptr as *const RiSession) };
605    session.expires_at as jlong
606}
607
608#[no_mangle]
609pub extern "system" fn Java_com_dunimd_ri_auth_RiSession_getIpAddress0(
610    mut env: JNIEnv,
611    _class: JClass,
612    ptr: jlong,
613) -> jstring {
614    if !check_not_null(&mut env, ptr, "RiSession") {
615        return std::ptr::null_mut();
616    }
617
618    let session = unsafe { &*(ptr as *const RiSession) };
619    match &session.ip_address {
620        Some(ip) => env
621            .new_string(ip)
622            .expect("Failed to create string")
623            .into_raw(),
624        None => std::ptr::null_mut(),
625    }
626}
627
628#[no_mangle]
629pub extern "system" fn Java_com_dunimd_ri_auth_RiSession_getUserAgent0(
630    mut env: JNIEnv,
631    _class: JClass,
632    ptr: jlong,
633) -> jstring {
634    if !check_not_null(&mut env, ptr, "RiSession") {
635        return std::ptr::null_mut();
636    }
637
638    let session = unsafe { &*(ptr as *const RiSession) };
639    match &session.user_agent {
640        Some(ua) => env
641            .new_string(ua)
642            .expect("Failed to create string")
643            .into_raw(),
644        None => std::ptr::null_mut(),
645    }
646}
647
648#[no_mangle]
649pub extern "system" fn Java_com_dunimd_ri_auth_RiSession_isExpired0(
650    mut env: JNIEnv,
651    _class: JClass,
652    ptr: jlong,
653) -> jboolean {
654    if !check_not_null(&mut env, ptr, "RiSession") {
655        return 0;
656    }
657
658    let session = unsafe { &*(ptr as *const RiSession) };
659    if session.is_expired() {
660        1
661    } else {
662        0
663    }
664}
665
666#[no_mangle]
667pub extern "system" fn Java_com_dunimd_ri_auth_RiSession_getData0(
668    mut env: JNIEnv,
669    _class: JClass,
670    ptr: jlong,
671    key: JString,
672) -> jstring {
673    if !check_not_null(&mut env, ptr, "RiSession") {
674        return std::ptr::null_mut();
675    }
676
677    let session = unsafe { &*(ptr as *const RiSession) };
678    let key_str: String = env.get_string(&key).expect("Failed to get key").into();
679
680    match session.get_data(&key_str) {
681        Some(value) => env
682            .new_string(value)
683            .expect("Failed to create string")
684            .into_raw(),
685        None => std::ptr::null_mut(),
686    }
687}
688
689#[no_mangle]
690pub extern "system" fn Java_com_dunimd_ri_auth_RiSession_setData0(
691    mut env: JNIEnv,
692    _class: JClass,
693    ptr: jlong,
694    key: JString,
695    value: JString,
696) {
697    if !check_not_null(&mut env, ptr, "RiSession") {
698        return;
699    }
700
701    let session = unsafe { &mut *(ptr as *mut RiSession) };
702    let key_str: String = env.get_string(&key).expect("Failed to get key").into();
703    let value_str: String = env.get_string(&value).expect("Failed to get value").into();
704
705    session.set_data(key_str, value_str);
706}
707
708#[no_mangle]
709pub extern "system" fn Java_com_dunimd_ri_auth_RiSession_free0(
710    _env: JNIEnv,
711    _class: JClass,
712    ptr: jlong,
713) {
714    if ptr != 0 {
715        unsafe {
716            let _ = Box::from_raw(ptr as *mut RiSession);
717        }
718    }
719}
720
721// =============================================================================
722// RiSessionManager JNI Bindings
723// =============================================================================
724
725#[no_mangle]
726pub extern "system" fn Java_com_dunimd_ri_auth_RiSessionManager_new0(
727    _env: JNIEnv,
728    _class: JClass,
729    timeout_secs: jlong,
730) -> jlong {
731    let manager = Box::new(RiSessionManager::new(timeout_secs as u64));
732    Box::into_raw(manager) as jlong
733}
734
735#[no_mangle]
736pub extern "system" fn Java_com_dunimd_ri_auth_RiSessionManager_createSession0(
737    mut env: JNIEnv,
738    _class: JClass,
739    ptr: jlong,
740    user_id: JString,
741    ip_address: JString,
742    user_agent: JString,
743) -> jstring {
744    if !check_not_null(&mut env, ptr, "RiSessionManager") {
745        return std::ptr::null_mut();
746    }
747
748    let manager = unsafe { &*(ptr as *const RiSessionManager) };
749    let user_id_str: String = env
750        .get_string(&user_id)
751        .expect("Failed to get user_id")
752        .into();
753
754    let ip_str = if ip_address.is_null() {
755        None
756    } else {
757        Some(
758            env.get_string(&ip_address)
759                .expect("Failed to get ip")
760                .into(),
761        )
762    };
763
764    let ua_str = if user_agent.is_null() {
765        None
766    } else {
767        Some(
768            env.get_string(&user_agent)
769                .expect("Failed to get user_agent")
770                .into(),
771        )
772    };
773
774    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
775    match rt.block_on(async { manager.create_session(user_id_str, ip_str, ua_str).await }) {
776        Ok(session_id) => env
777            .new_string(&session_id)
778            .expect("Failed to create string")
779            .into_raw(),
780        Err(_) => std::ptr::null_mut(),
781    }
782}
783
784#[no_mangle]
785pub extern "system" fn Java_com_dunimd_ri_auth_RiSessionManager_getSession0(
786    mut env: JNIEnv,
787    _class: JClass,
788    ptr: jlong,
789    session_id: JString,
790) -> jlong {
791    if !check_not_null(&mut env, ptr, "RiSessionManager") {
792        return 0;
793    }
794
795    let manager = unsafe { &*(ptr as *const RiSessionManager) };
796    let session_id_str: String = env
797        .get_string(&session_id)
798        .expect("Failed to get session_id")
799        .into();
800
801    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
802    match rt.block_on(async { manager.get_session(&session_id_str).await }) {
803        Ok(Some(session)) => {
804            let session_box = Box::new(session);
805            Box::into_raw(session_box) as jlong
806        }
807        _ => 0,
808    }
809}
810
811#[no_mangle]
812pub extern "system" fn Java_com_dunimd_ri_auth_RiSessionManager_destroySession0(
813    mut env: JNIEnv,
814    _class: JClass,
815    ptr: jlong,
816    session_id: JString,
817) -> jboolean {
818    if !check_not_null(&mut env, ptr, "RiSessionManager") {
819        return 0;
820    }
821
822    let manager = unsafe { &*(ptr as *const RiSessionManager) };
823    let session_id_str: String = env
824        .get_string(&session_id)
825        .expect("Failed to get session_id")
826        .into();
827
828    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
829    match rt.block_on(async { manager.destroy_session(&session_id_str).await }) {
830        Ok(result) => {
831            if result {
832                1
833            } else {
834                0
835            }
836        }
837        Err(_) => 0,
838    }
839}
840
841#[no_mangle]
842pub extern "system" fn Java_com_dunimd_ri_auth_RiSessionManager_extendSession0(
843    mut env: JNIEnv,
844    _class: JClass,
845    ptr: jlong,
846    session_id: JString,
847) -> jboolean {
848    if !check_not_null(&mut env, ptr, "RiSessionManager") {
849        return 0;
850    }
851
852    let manager = unsafe { &*(ptr as *const RiSessionManager) };
853    let session_id_str: String = env
854        .get_string(&session_id)
855        .expect("Failed to get session_id")
856        .into();
857
858    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
859    match rt.block_on(async { manager.extend_session(&session_id_str).await }) {
860        Ok(result) => {
861            if result {
862                1
863            } else {
864                0
865            }
866        }
867        Err(_) => 0,
868    }
869}
870
871#[no_mangle]
872pub extern "system" fn Java_com_dunimd_ri_auth_RiSessionManager_cleanupExpired0(
873    mut env: JNIEnv,
874    _class: JClass,
875    ptr: jlong,
876) -> jint {
877    if !check_not_null(&mut env, ptr, "RiSessionManager") {
878        return 0;
879    }
880
881    let manager = unsafe { &*(ptr as *const RiSessionManager) };
882
883    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
884    match rt.block_on(async { manager.cleanup_expired().await }) {
885        Ok(count) => count as jint,
886        Err(_) => 0,
887    }
888}
889
890#[no_mangle]
891pub extern "system" fn Java_com_dunimd_ri_auth_RiSessionManager_getTimeout0(
892    mut env: JNIEnv,
893    _class: JClass,
894    ptr: jlong,
895) -> jlong {
896    if !check_not_null(&mut env, ptr, "RiSessionManager") {
897        return 0;
898    }
899
900    let manager = unsafe { &*(ptr as *const RiSessionManager) };
901    manager.get_timeout() as jlong
902}
903
904#[no_mangle]
905pub extern "system" fn Java_com_dunimd_ri_auth_RiSessionManager_free0(
906    _env: JNIEnv,
907    _class: JClass,
908    ptr: jlong,
909) {
910    if ptr != 0 {
911        unsafe {
912            let _ = Box::from_raw(ptr as *mut RiSessionManager);
913        }
914    }
915}
916
917// =============================================================================
918// RiPermission JNI Bindings
919// =============================================================================
920
921#[no_mangle]
922pub extern "system" fn Java_com_dunimd_ri_auth_RiPermission_new0(
923    mut env: JNIEnv,
924    _class: JClass,
925    id: JString,
926    name: JString,
927    description: JString,
928    resource: JString,
929    action: JString,
930) -> jlong {
931    let id_str: String = env.get_string(&id).expect("Failed to get id").into();
932    let name_str: String = env.get_string(&name).expect("Failed to get name").into();
933    let desc_str: String = env
934        .get_string(&description)
935        .expect("Failed to get description")
936        .into();
937    let resource_str: String = env
938        .get_string(&resource)
939        .expect("Failed to get resource")
940        .into();
941    let action_str: String = env
942        .get_string(&action)
943        .expect("Failed to get action")
944        .into();
945
946    let permission = Box::new(RiPermission {
947        id: id_str,
948        name: name_str,
949        description: desc_str,
950        resource: resource_str,
951        action: action_str,
952    });
953    Box::into_raw(permission) as jlong
954}
955
956#[no_mangle]
957pub extern "system" fn Java_com_dunimd_ri_auth_RiPermission_getId0(
958    mut env: JNIEnv,
959    _class: JClass,
960    ptr: jlong,
961) -> jstring {
962    if !check_not_null(&mut env, ptr, "RiPermission") {
963        return std::ptr::null_mut();
964    }
965
966    let permission = unsafe { &*(ptr as *const RiPermission) };
967    env.new_string(&permission.id)
968        .expect("Failed to create string")
969        .into_raw()
970}
971
972#[no_mangle]
973pub extern "system" fn Java_com_dunimd_ri_auth_RiPermission_getName0(
974    mut env: JNIEnv,
975    _class: JClass,
976    ptr: jlong,
977) -> jstring {
978    if !check_not_null(&mut env, ptr, "RiPermission") {
979        return std::ptr::null_mut();
980    }
981
982    let permission = unsafe { &*(ptr as *const RiPermission) };
983    env.new_string(&permission.name)
984        .expect("Failed to create string")
985        .into_raw()
986}
987
988#[no_mangle]
989pub extern "system" fn Java_com_dunimd_ri_auth_RiPermission_getDescription0(
990    mut env: JNIEnv,
991    _class: JClass,
992    ptr: jlong,
993) -> jstring {
994    if !check_not_null(&mut env, ptr, "RiPermission") {
995        return std::ptr::null_mut();
996    }
997
998    let permission = unsafe { &*(ptr as *const RiPermission) };
999    env.new_string(&permission.description)
1000        .expect("Failed to create string")
1001        .into_raw()
1002}
1003
1004#[no_mangle]
1005pub extern "system" fn Java_com_dunimd_ri_auth_RiPermission_getResource0(
1006    mut env: JNIEnv,
1007    _class: JClass,
1008    ptr: jlong,
1009) -> jstring {
1010    if !check_not_null(&mut env, ptr, "RiPermission") {
1011        return std::ptr::null_mut();
1012    }
1013
1014    let permission = unsafe { &*(ptr as *const RiPermission) };
1015    env.new_string(&permission.resource)
1016        .expect("Failed to create string")
1017        .into_raw()
1018}
1019
1020#[no_mangle]
1021pub extern "system" fn Java_com_dunimd_ri_auth_RiPermission_getAction0(
1022    mut env: JNIEnv,
1023    _class: JClass,
1024    ptr: jlong,
1025) -> jstring {
1026    if !check_not_null(&mut env, ptr, "RiPermission") {
1027        return std::ptr::null_mut();
1028    }
1029
1030    let permission = unsafe { &*(ptr as *const RiPermission) };
1031    env.new_string(&permission.action)
1032        .expect("Failed to create string")
1033        .into_raw()
1034}
1035
1036#[no_mangle]
1037pub extern "system" fn Java_com_dunimd_ri_auth_RiPermission_free0(
1038    _env: JNIEnv,
1039    _class: JClass,
1040    ptr: jlong,
1041) {
1042    if ptr != 0 {
1043        unsafe {
1044            let _ = Box::from_raw(ptr as *mut RiPermission);
1045        }
1046    }
1047}
1048
1049// =============================================================================
1050// RiRole JNI Bindings
1051// =============================================================================
1052
1053#[no_mangle]
1054pub extern "system" fn Java_com_dunimd_ri_auth_RiRole_new0(
1055    mut env: JNIEnv,
1056    _class: JClass,
1057    id: JString,
1058    name: JString,
1059    description: JString,
1060    permissions: JObjectArray,
1061    is_system: jboolean,
1062) -> jlong {
1063    let id_str: String = env.get_string(&id).expect("Failed to get id").into();
1064    let name_str: String = env.get_string(&name).expect("Failed to get name").into();
1065    let desc_str: String = env
1066        .get_string(&description)
1067        .expect("Failed to get description")
1068        .into();
1069
1070    let perms_len = env
1071        .get_array_length(&permissions)
1072        .expect("Failed to get permissions length");
1073    let mut perms_set = HashSet::with_capacity(perms_len as usize);
1074    for i in 0..perms_len {
1075        if let Ok(Some(elem)) = env.get_object_array_element(&permissions, i) {
1076            let perm_str: String = env
1077                .get_string(&JString::from(elem))
1078                .expect("Failed to get permission")
1079                .into();
1080            perms_set.insert(perm_str);
1081        }
1082    }
1083
1084    let role = Box::new(RiRole {
1085        id: id_str,
1086        name: name_str,
1087        description: desc_str,
1088        permissions: perms_set,
1089        is_system: is_system != 0,
1090    });
1091    Box::into_raw(role) as jlong
1092}
1093
1094#[no_mangle]
1095pub extern "system" fn Java_com_dunimd_ri_auth_RiRole_getId0(
1096    mut env: JNIEnv,
1097    _class: JClass,
1098    ptr: jlong,
1099) -> jstring {
1100    if !check_not_null(&mut env, ptr, "RiRole") {
1101        return std::ptr::null_mut();
1102    }
1103
1104    let role = unsafe { &*(ptr as *const RiRole) };
1105    env.new_string(&role.id)
1106        .expect("Failed to create string")
1107        .into_raw()
1108}
1109
1110#[no_mangle]
1111pub extern "system" fn Java_com_dunimd_ri_auth_RiRole_getName0(
1112    mut env: JNIEnv,
1113    _class: JClass,
1114    ptr: jlong,
1115) -> jstring {
1116    if !check_not_null(&mut env, ptr, "RiRole") {
1117        return std::ptr::null_mut();
1118    }
1119
1120    let role = unsafe { &*(ptr as *const RiRole) };
1121    env.new_string(&role.name)
1122        .expect("Failed to create string")
1123        .into_raw()
1124}
1125
1126#[no_mangle]
1127pub extern "system" fn Java_com_dunimd_ri_auth_RiRole_getDescription0(
1128    mut env: JNIEnv,
1129    _class: JClass,
1130    ptr: jlong,
1131) -> jstring {
1132    if !check_not_null(&mut env, ptr, "RiRole") {
1133        return std::ptr::null_mut();
1134    }
1135
1136    let role = unsafe { &*(ptr as *const RiRole) };
1137    env.new_string(&role.description)
1138        .expect("Failed to create string")
1139        .into_raw()
1140}
1141
1142#[no_mangle]
1143pub extern "system" fn Java_com_dunimd_ri_auth_RiRole_getPermissions0(
1144    mut env: JNIEnv,
1145    _class: JClass,
1146    ptr: jlong,
1147) -> jobjectArray {
1148    if !check_not_null(&mut env, ptr, "RiRole") {
1149        return std::ptr::null_mut();
1150    }
1151
1152    let role = unsafe { &*(ptr as *const RiRole) };
1153    let perms: Vec<String> = role.permissions.iter().cloned().collect();
1154
1155    let string_class = env
1156        .find_class("java/lang/String")
1157        .expect("Failed to find String class");
1158    let array = env
1159        .new_object_array(perms.len() as jint, string_class, std::ptr::null_mut())
1160        .expect("Failed to create array");
1161
1162    for (i, perm) in perms.iter().enumerate() {
1163        let jstr = env.new_string(perm).expect("Failed to create string");
1164        env.set_object_array_element(&array, i as jint, jstr)
1165            .expect("Failed to set array element");
1166    }
1167
1168    array.into_raw()
1169}
1170
1171#[no_mangle]
1172pub extern "system" fn Java_com_dunimd_ri_auth_RiRole_isSystem0(
1173    mut env: JNIEnv,
1174    _class: JClass,
1175    ptr: jlong,
1176) -> jboolean {
1177    if !check_not_null(&mut env, ptr, "RiRole") {
1178        return 0;
1179    }
1180
1181    let role = unsafe { &*(ptr as *const RiRole) };
1182    if role.is_system {
1183        1
1184    } else {
1185        0
1186    }
1187}
1188
1189#[no_mangle]
1190pub extern "system" fn Java_com_dunimd_ri_auth_RiRole_hasPermission0(
1191    mut env: JNIEnv,
1192    _class: JClass,
1193    ptr: jlong,
1194    permission_id: JString,
1195) -> jboolean {
1196    if !check_not_null(&mut env, ptr, "RiRole") {
1197        return 0;
1198    }
1199
1200    let role = unsafe { &*(ptr as *const RiRole) };
1201    let perm_str: String = env
1202        .get_string(&permission_id)
1203        .expect("Failed to get permission_id")
1204        .into();
1205
1206    if role.has_permission(&perm_str) {
1207        1
1208    } else {
1209        0
1210    }
1211}
1212
1213#[no_mangle]
1214pub extern "system" fn Java_com_dunimd_ri_auth_RiRole_addPermission0(
1215    mut env: JNIEnv,
1216    _class: JClass,
1217    ptr: jlong,
1218    permission_id: JString,
1219) {
1220    if !check_not_null(&mut env, ptr, "RiRole") {
1221        return;
1222    }
1223
1224    let role = unsafe { &mut *(ptr as *mut RiRole) };
1225    let perm_str: String = env
1226        .get_string(&permission_id)
1227        .expect("Failed to get permission_id")
1228        .into();
1229
1230    role.add_permission(perm_str);
1231}
1232
1233#[no_mangle]
1234pub extern "system" fn Java_com_dunimd_ri_auth_RiRole_free0(
1235    _env: JNIEnv,
1236    _class: JClass,
1237    ptr: jlong,
1238) {
1239    if ptr != 0 {
1240        unsafe {
1241            let _ = Box::from_raw(ptr as *mut RiRole);
1242        }
1243    }
1244}
1245
1246// =============================================================================
1247// RiPermissionManager JNI Bindings
1248// =============================================================================
1249
1250#[no_mangle]
1251pub extern "system" fn Java_com_dunimd_ri_auth_RiPermissionManager_new0(
1252    _env: JNIEnv,
1253    _class: JClass,
1254) -> jlong {
1255    let manager = Box::new(RiPermissionManager::new());
1256    Box::into_raw(manager) as jlong
1257}
1258
1259#[no_mangle]
1260pub extern "system" fn Java_com_dunimd_ri_auth_RiPermissionManager_createPermission0(
1261    mut env: JNIEnv,
1262    _class: JClass,
1263    ptr: jlong,
1264    permission_ptr: jlong,
1265) {
1266    if !check_not_null(&mut env, ptr, "RiPermissionManager") {
1267        return;
1268    }
1269    if !check_not_null(&mut env, permission_ptr, "RiPermission") {
1270        return;
1271    }
1272
1273    let manager = unsafe { &*(ptr as *const RiPermissionManager) };
1274    let permission = unsafe { &*(permission_ptr as *const RiPermission) };
1275
1276    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
1277    let _ = rt.block_on(async { manager.create_permission(permission.clone()).await });
1278}
1279
1280#[no_mangle]
1281pub extern "system" fn Java_com_dunimd_ri_auth_RiPermissionManager_getPermission0(
1282    mut env: JNIEnv,
1283    _class: JClass,
1284    ptr: jlong,
1285    permission_id: JString,
1286) -> jlong {
1287    if !check_not_null(&mut env, ptr, "RiPermissionManager") {
1288        return 0;
1289    }
1290
1291    let manager = unsafe { &*(ptr as *const RiPermissionManager) };
1292    let perm_id_str: String = env
1293        .get_string(&permission_id)
1294        .expect("Failed to get permission_id")
1295        .into();
1296
1297    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
1298    match rt.block_on(async { manager.get_permission(&perm_id_str).await }) {
1299        Ok(Some(perm)) => {
1300            let perm_box = Box::new(perm);
1301            Box::into_raw(perm_box) as jlong
1302        }
1303        _ => 0,
1304    }
1305}
1306
1307#[no_mangle]
1308pub extern "system" fn Java_com_dunimd_ri_auth_RiPermissionManager_createRole0(
1309    mut env: JNIEnv,
1310    _class: JClass,
1311    ptr: jlong,
1312    role_ptr: jlong,
1313) {
1314    if !check_not_null(&mut env, ptr, "RiPermissionManager") {
1315        return;
1316    }
1317    if !check_not_null(&mut env, role_ptr, "RiRole") {
1318        return;
1319    }
1320
1321    let manager = unsafe { &*(ptr as *const RiPermissionManager) };
1322    let role = unsafe { &*(role_ptr as *const RiRole) };
1323
1324    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
1325    let _ = rt.block_on(async { manager.create_role(role.clone()).await });
1326}
1327
1328#[no_mangle]
1329pub extern "system" fn Java_com_dunimd_ri_auth_RiPermissionManager_getRole0(
1330    mut env: JNIEnv,
1331    _class: JClass,
1332    ptr: jlong,
1333    role_id: JString,
1334) -> jlong {
1335    if !check_not_null(&mut env, ptr, "RiPermissionManager") {
1336        return 0;
1337    }
1338
1339    let manager = unsafe { &*(ptr as *const RiPermissionManager) };
1340    let role_id_str: String = env
1341        .get_string(&role_id)
1342        .expect("Failed to get role_id")
1343        .into();
1344
1345    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
1346    match rt.block_on(async { manager.get_role(&role_id_str).await }) {
1347        Ok(Some(role)) => {
1348            let role_box = Box::new(role);
1349            Box::into_raw(role_box) as jlong
1350        }
1351        _ => 0,
1352    }
1353}
1354
1355#[no_mangle]
1356pub extern "system" fn Java_com_dunimd_ri_auth_RiPermissionManager_assignRoleToUser0(
1357    mut env: JNIEnv,
1358    _class: JClass,
1359    ptr: jlong,
1360    user_id: JString,
1361    role_id: JString,
1362) -> jboolean {
1363    if !check_not_null(&mut env, ptr, "RiPermissionManager") {
1364        return 0;
1365    }
1366
1367    let manager = unsafe { &*(ptr as *const RiPermissionManager) };
1368    let user_id_str: String = env
1369        .get_string(&user_id)
1370        .expect("Failed to get user_id")
1371        .into();
1372    let role_id_str: String = env
1373        .get_string(&role_id)
1374        .expect("Failed to get role_id")
1375        .into();
1376
1377    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
1378    match rt.block_on(async { manager.assign_role_to_user(user_id_str, role_id_str).await }) {
1379        Ok(result) => {
1380            if result {
1381                1
1382            } else {
1383                0
1384            }
1385        }
1386        Err(_) => 0,
1387    }
1388}
1389
1390#[no_mangle]
1391pub extern "system" fn Java_com_dunimd_ri_auth_RiPermissionManager_removeRoleFromUser0(
1392    mut env: JNIEnv,
1393    _class: JClass,
1394    ptr: jlong,
1395    user_id: JString,
1396    role_id: JString,
1397) -> jboolean {
1398    if !check_not_null(&mut env, ptr, "RiPermissionManager") {
1399        return 0;
1400    }
1401
1402    let manager = unsafe { &*(ptr as *const RiPermissionManager) };
1403    let user_id_str: String = env
1404        .get_string(&user_id)
1405        .expect("Failed to get user_id")
1406        .into();
1407    let role_id_str: String = env
1408        .get_string(&role_id)
1409        .expect("Failed to get role_id")
1410        .into();
1411
1412    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
1413    match rt.block_on(async {
1414        manager
1415            .remove_role_from_user(&user_id_str, &role_id_str)
1416            .await
1417    }) {
1418        Ok(result) => {
1419            if result {
1420                1
1421            } else {
1422                0
1423            }
1424        }
1425        Err(_) => 0,
1426    }
1427}
1428
1429#[no_mangle]
1430pub extern "system" fn Java_com_dunimd_ri_auth_RiPermissionManager_getUserRoles0(
1431    mut env: JNIEnv,
1432    _class: JClass,
1433    ptr: jlong,
1434    user_id: JString,
1435) -> jlongArray {
1436    if !check_not_null(&mut env, ptr, "RiPermissionManager") {
1437        return std::ptr::null_mut();
1438    }
1439
1440    let manager = unsafe { &*(ptr as *const RiPermissionManager) };
1441    let user_id_str: String = env
1442        .get_string(&user_id)
1443        .expect("Failed to get user_id")
1444        .into();
1445
1446    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
1447    let roles = rt
1448        .block_on(async { manager.get_user_roles(&user_id_str).await })
1449        .unwrap_or_default();
1450
1451    let ptrs: Vec<jlong> = roles
1452        .into_iter()
1453        .map(|r| Box::into_raw(Box::new(r)) as jlong)
1454        .collect();
1455
1456    let long_class = env
1457        .find_class("java/lang/Long")
1458        .expect("Failed to find Long class");
1459    let array = env
1460        .new_long_array(ptrs.len() as jint)
1461        .expect("Failed to create array");
1462    env.set_long_array_region(&array, 0, &ptrs)
1463        .expect("Failed to set array");
1464
1465    array.into_raw()
1466}
1467
1468use jni::sys::jlongArray;
1469
1470#[no_mangle]
1471pub extern "system" fn Java_com_dunimd_ri_auth_RiPermissionManager_hasPermission0(
1472    mut env: JNIEnv,
1473    _class: JClass,
1474    ptr: jlong,
1475    user_id: JString,
1476    permission_id: JString,
1477) -> jboolean {
1478    if !check_not_null(&mut env, ptr, "RiPermissionManager") {
1479        return 0;
1480    }
1481
1482    let manager = unsafe { &*(ptr as *const RiPermissionManager) };
1483    let user_id_str: String = env
1484        .get_string(&user_id)
1485        .expect("Failed to get user_id")
1486        .into();
1487    let perm_id_str: String = env
1488        .get_string(&permission_id)
1489        .expect("Failed to get permission_id")
1490        .into();
1491
1492    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
1493    match rt.block_on(async { manager.has_permission(&user_id_str, &perm_id_str).await }) {
1494        Ok(result) => {
1495            if result {
1496                1
1497            } else {
1498                0
1499            }
1500        }
1501        Err(_) => 0,
1502    }
1503}
1504
1505#[no_mangle]
1506pub extern "system" fn Java_com_dunimd_ri_auth_RiPermissionManager_getUserPermissions0(
1507    mut env: JNIEnv,
1508    _class: JClass,
1509    ptr: jlong,
1510    user_id: JString,
1511) -> jobjectArray {
1512    if !check_not_null(&mut env, ptr, "RiPermissionManager") {
1513        return std::ptr::null_mut();
1514    }
1515
1516    let manager = unsafe { &*(ptr as *const RiPermissionManager) };
1517    let user_id_str: String = env
1518        .get_string(&user_id)
1519        .expect("Failed to get user_id")
1520        .into();
1521
1522    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
1523    let perms = rt
1524        .block_on(async { manager.get_user_permissions(&user_id_str).await })
1525        .unwrap_or_default();
1526
1527    let perms_vec: Vec<String> = perms.into_iter().collect();
1528
1529    let string_class = env
1530        .find_class("java/lang/String")
1531        .expect("Failed to find String class");
1532    let array = env
1533        .new_object_array(perms_vec.len() as jint, string_class, std::ptr::null_mut())
1534        .expect("Failed to create array");
1535
1536    for (i, perm) in perms_vec.iter().enumerate() {
1537        let jstr = env.new_string(perm).expect("Failed to create string");
1538        env.set_object_array_element(&array, i as jint, jstr)
1539            .expect("Failed to set array element");
1540    }
1541
1542    array.into_raw()
1543}
1544
1545#[no_mangle]
1546pub extern "system" fn Java_com_dunimd_ri_auth_RiPermissionManager_deletePermission0(
1547    mut env: JNIEnv,
1548    _class: JClass,
1549    ptr: jlong,
1550    permission_id: JString,
1551) -> jboolean {
1552    if !check_not_null(&mut env, ptr, "RiPermissionManager") {
1553        return 0;
1554    }
1555
1556    let manager = unsafe { &*(ptr as *const RiPermissionManager) };
1557    let perm_id_str: String = env
1558        .get_string(&permission_id)
1559        .expect("Failed to get permission_id")
1560        .into();
1561
1562    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
1563    match rt.block_on(async { manager.delete_permission(&perm_id_str).await }) {
1564        Ok(result) => {
1565            if result {
1566                1
1567            } else {
1568                0
1569            }
1570        }
1571        Err(_) => 0,
1572    }
1573}
1574
1575#[no_mangle]
1576pub extern "system" fn Java_com_dunimd_ri_auth_RiPermissionManager_deleteRole0(
1577    mut env: JNIEnv,
1578    _class: JClass,
1579    ptr: jlong,
1580    role_id: JString,
1581) -> jboolean {
1582    if !check_not_null(&mut env, ptr, "RiPermissionManager") {
1583        return 0;
1584    }
1585
1586    let manager = unsafe { &*(ptr as *const RiPermissionManager) };
1587    let role_id_str: String = env
1588        .get_string(&role_id)
1589        .expect("Failed to get role_id")
1590        .into();
1591
1592    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
1593    match rt.block_on(async { manager.delete_role(&role_id_str).await }) {
1594        Ok(result) => {
1595            if result {
1596                1
1597            } else {
1598                0
1599            }
1600        }
1601        Err(_) => 0,
1602    }
1603}
1604
1605#[no_mangle]
1606pub extern "system" fn Java_com_dunimd_ri_auth_RiPermissionManager_listPermissions0(
1607    mut env: JNIEnv,
1608    _class: JClass,
1609    ptr: jlong,
1610) -> jlongArray {
1611    if !check_not_null(&mut env, ptr, "RiPermissionManager") {
1612        return std::ptr::null_mut();
1613    }
1614
1615    let manager = unsafe { &*(ptr as *const RiPermissionManager) };
1616
1617    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
1618    let perms = rt
1619        .block_on(async { manager.list_permissions().await })
1620        .unwrap_or_default();
1621
1622    let ptrs: Vec<jlong> = perms
1623        .into_iter()
1624        .map(|p| Box::into_raw(Box::new(p)) as jlong)
1625        .collect();
1626
1627    let array = env
1628        .new_long_array(ptrs.len() as jint)
1629        .expect("Failed to create array");
1630    env.set_long_array_region(&array, 0, &ptrs)
1631        .expect("Failed to set array");
1632
1633    array.into_raw()
1634}
1635
1636#[no_mangle]
1637pub extern "system" fn Java_com_dunimd_ri_auth_RiPermissionManager_listRoles0(
1638    mut env: JNIEnv,
1639    _class: JClass,
1640    ptr: jlong,
1641) -> jlongArray {
1642    if !check_not_null(&mut env, ptr, "RiPermissionManager") {
1643        return std::ptr::null_mut();
1644    }
1645
1646    let manager = unsafe { &*(ptr as *const RiPermissionManager) };
1647
1648    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
1649    let roles = rt
1650        .block_on(async { manager.list_roles().await })
1651        .unwrap_or_default();
1652
1653    let ptrs: Vec<jlong> = roles
1654        .into_iter()
1655        .map(|r| Box::into_raw(Box::new(r)) as jlong)
1656        .collect();
1657
1658    let array = env
1659        .new_long_array(ptrs.len() as jint)
1660        .expect("Failed to create array");
1661    env.set_long_array_region(&array, 0, &ptrs)
1662        .expect("Failed to set array");
1663
1664    array.into_raw()
1665}
1666
1667#[no_mangle]
1668pub extern "system" fn Java_com_dunimd_ri_auth_RiPermissionManager_free0(
1669    _env: JNIEnv,
1670    _class: JClass,
1671    ptr: jlong,
1672) {
1673    if ptr != 0 {
1674        unsafe {
1675            let _ = Box::from_raw(ptr as *mut RiPermissionManager);
1676        }
1677    }
1678}
1679
1680// =============================================================================
1681// RiOAuthProvider JNI Bindings
1682// =============================================================================
1683
1684#[no_mangle]
1685pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthProvider_new0(
1686    mut env: JNIEnv,
1687    _class: JClass,
1688    id: JString,
1689    name: JString,
1690    client_id: JString,
1691    client_secret: JString,
1692    auth_url: JString,
1693    token_url: JString,
1694    user_info_url: JString,
1695    scopes: JObjectArray,
1696    enabled: jboolean,
1697    redirect_uri: JString,
1698) -> jlong {
1699    let id_str: String = env.get_string(&id).expect("Failed to get id").into();
1700    let name_str: String = env.get_string(&name).expect("Failed to get name").into();
1701    let client_id_str: String = env
1702        .get_string(&client_id)
1703        .expect("Failed to get client_id")
1704        .into();
1705    let client_secret_str: String = env
1706        .get_string(&client_secret)
1707        .expect("Failed to get client_secret")
1708        .into();
1709    let auth_url_str: String = env
1710        .get_string(&auth_url)
1711        .expect("Failed to get auth_url")
1712        .into();
1713    let token_url_str: String = env
1714        .get_string(&token_url)
1715        .expect("Failed to get token_url")
1716        .into();
1717    let user_info_url_str: String = env
1718        .get_string(&user_info_url)
1719        .expect("Failed to get user_info_url")
1720        .into();
1721
1722    let scopes_len = env
1723        .get_array_length(&scopes)
1724        .expect("Failed to get scopes length");
1725    let mut scopes_vec = Vec::with_capacity(scopes_len as usize);
1726    for i in 0..scopes_len {
1727        if let Ok(Some(elem)) = env.get_object_array_element(&scopes, i) {
1728            let scope_str: String = env
1729                .get_string(&JString::from(elem))
1730                .expect("Failed to get scope")
1731                .into();
1732            scopes_vec.push(scope_str);
1733        }
1734    }
1735
1736    let redirect_uri_opt = if redirect_uri.is_null() {
1737        None
1738    } else {
1739        Some(
1740            env.get_string(&redirect_uri)
1741                .expect("Failed to get redirect_uri")
1742                .into(),
1743        )
1744    };
1745
1746    let provider = Box::new(RiOAuthProvider {
1747        id: id_str,
1748        name: name_str,
1749        client_id: client_id_str,
1750        client_secret: client_secret_str,
1751        auth_url: auth_url_str,
1752        token_url: token_url_str,
1753        user_info_url: user_info_url_str,
1754        scopes: scopes_vec,
1755        enabled: enabled != 0,
1756        redirect_uri: redirect_uri_opt,
1757    });
1758    Box::into_raw(provider) as jlong
1759}
1760
1761#[no_mangle]
1762pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthProvider_getId0(
1763    mut env: JNIEnv,
1764    _class: JClass,
1765    ptr: jlong,
1766) -> jstring {
1767    if !check_not_null(&mut env, ptr, "RiOAuthProvider") {
1768        return std::ptr::null_mut();
1769    }
1770
1771    let provider = unsafe { &*(ptr as *const RiOAuthProvider) };
1772    env.new_string(&provider.id)
1773        .expect("Failed to create string")
1774        .into_raw()
1775}
1776
1777#[no_mangle]
1778pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthProvider_getName0(
1779    mut env: JNIEnv,
1780    _class: JClass,
1781    ptr: jlong,
1782) -> jstring {
1783    if !check_not_null(&mut env, ptr, "RiOAuthProvider") {
1784        return std::ptr::null_mut();
1785    }
1786
1787    let provider = unsafe { &*(ptr as *const RiOAuthProvider) };
1788    env.new_string(&provider.name)
1789        .expect("Failed to create string")
1790        .into_raw()
1791}
1792
1793#[no_mangle]
1794pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthProvider_getClientId0(
1795    mut env: JNIEnv,
1796    _class: JClass,
1797    ptr: jlong,
1798) -> jstring {
1799    if !check_not_null(&mut env, ptr, "RiOAuthProvider") {
1800        return std::ptr::null_mut();
1801    }
1802
1803    let provider = unsafe { &*(ptr as *const RiOAuthProvider) };
1804    env.new_string(&provider.client_id)
1805        .expect("Failed to create string")
1806        .into_raw()
1807}
1808
1809#[no_mangle]
1810pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthProvider_getAuthUrl0(
1811    mut env: JNIEnv,
1812    _class: JClass,
1813    ptr: jlong,
1814) -> jstring {
1815    if !check_not_null(&mut env, ptr, "RiOAuthProvider") {
1816        return std::ptr::null_mut();
1817    }
1818
1819    let provider = unsafe { &*(ptr as *const RiOAuthProvider) };
1820    env.new_string(&provider.auth_url)
1821        .expect("Failed to create string")
1822        .into_raw()
1823}
1824
1825#[no_mangle]
1826pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthProvider_getTokenUrl0(
1827    mut env: JNIEnv,
1828    _class: JClass,
1829    ptr: jlong,
1830) -> jstring {
1831    if !check_not_null(&mut env, ptr, "RiOAuthProvider") {
1832        return std::ptr::null_mut();
1833    }
1834
1835    let provider = unsafe { &*(ptr as *const RiOAuthProvider) };
1836    env.new_string(&provider.token_url)
1837        .expect("Failed to create string")
1838        .into_raw()
1839}
1840
1841#[no_mangle]
1842pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthProvider_getUserInfoUrl0(
1843    mut env: JNIEnv,
1844    _class: JClass,
1845    ptr: jlong,
1846) -> jstring {
1847    if !check_not_null(&mut env, ptr, "RiOAuthProvider") {
1848        return std::ptr::null_mut();
1849    }
1850
1851    let provider = unsafe { &*(ptr as *const RiOAuthProvider) };
1852    env.new_string(&provider.user_info_url)
1853        .expect("Failed to create string")
1854        .into_raw()
1855}
1856
1857#[no_mangle]
1858pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthProvider_getScopes0(
1859    mut env: JNIEnv,
1860    _class: JClass,
1861    ptr: jlong,
1862) -> jobjectArray {
1863    if !check_not_null(&mut env, ptr, "RiOAuthProvider") {
1864        return std::ptr::null_mut();
1865    }
1866
1867    let provider = unsafe { &*(ptr as *const RiOAuthProvider) };
1868
1869    let string_class = env
1870        .find_class("java/lang/String")
1871        .expect("Failed to find String class");
1872    let array = env
1873        .new_object_array(
1874            provider.scopes.len() as jint,
1875            string_class,
1876            std::ptr::null_mut(),
1877        )
1878        .expect("Failed to create array");
1879
1880    for (i, scope) in provider.scopes.iter().enumerate() {
1881        let jstr = env.new_string(scope).expect("Failed to create string");
1882        env.set_object_array_element(&array, i as jint, jstr)
1883            .expect("Failed to set array element");
1884    }
1885
1886    array.into_raw()
1887}
1888
1889#[no_mangle]
1890pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthProvider_isEnabled0(
1891    mut env: JNIEnv,
1892    _class: JClass,
1893    ptr: jlong,
1894) -> jboolean {
1895    if !check_not_null(&mut env, ptr, "RiOAuthProvider") {
1896        return 0;
1897    }
1898
1899    let provider = unsafe { &*(ptr as *const RiOAuthProvider) };
1900    if provider.enabled {
1901        1
1902    } else {
1903        0
1904    }
1905}
1906
1907#[no_mangle]
1908pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthProvider_getRedirectUri0(
1909    mut env: JNIEnv,
1910    _class: JClass,
1911    ptr: jlong,
1912) -> jstring {
1913    if !check_not_null(&mut env, ptr, "RiOAuthProvider") {
1914        return std::ptr::null_mut();
1915    }
1916
1917    let provider = unsafe { &*(ptr as *const RiOAuthProvider) };
1918    match &provider.redirect_uri {
1919        Some(uri) => env
1920            .new_string(uri)
1921            .expect("Failed to create string")
1922            .into_raw(),
1923        None => std::ptr::null_mut(),
1924    }
1925}
1926
1927#[no_mangle]
1928pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthProvider_free0(
1929    _env: JNIEnv,
1930    _class: JClass,
1931    ptr: jlong,
1932) {
1933    if ptr != 0 {
1934        unsafe {
1935            let _ = Box::from_raw(ptr as *mut RiOAuthProvider);
1936        }
1937    }
1938}
1939
1940// =============================================================================
1941// RiOAuthToken JNI Bindings
1942// =============================================================================
1943
1944#[no_mangle]
1945pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthToken_new0(
1946    mut env: JNIEnv,
1947    _class: JClass,
1948    access_token: JString,
1949    token_type: JString,
1950    refresh_token: JString,
1951    scope: JString,
1952    expires_in: jlong,
1953) -> jlong {
1954    let access_token_str: String = env
1955        .get_string(&access_token)
1956        .expect("Failed to get access_token")
1957        .into();
1958    let token_type_str: String = env
1959        .get_string(&token_type)
1960        .expect("Failed to get token_type")
1961        .into();
1962    let refresh_token_opt = if refresh_token.is_null() {
1963        None
1964    } else {
1965        Some(
1966            env.get_string(&refresh_token)
1967                .expect("Failed to get refresh_token")
1968                .into(),
1969        )
1970    };
1971    let scope_opt = if scope.is_null() {
1972        None
1973    } else {
1974        Some(env.get_string(&scope).expect("Failed to get scope").into())
1975    };
1976
1977    let token = Box::new(RiOAuthToken {
1978        access_token: access_token_str,
1979        token_type: token_type_str,
1980        refresh_token: refresh_token_opt,
1981        scope: scope_opt,
1982        expires_in: Some(expires_in),
1983    });
1984    Box::into_raw(token) as jlong
1985}
1986
1987#[no_mangle]
1988pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthToken_getAccessToken0(
1989    mut env: JNIEnv,
1990    _class: JClass,
1991    ptr: jlong,
1992) -> jstring {
1993    if !check_not_null(&mut env, ptr, "RiOAuthToken") {
1994        return std::ptr::null_mut();
1995    }
1996
1997    let token = unsafe { &*(ptr as *const RiOAuthToken) };
1998    env.new_string(&token.access_token)
1999        .expect("Failed to create string")
2000        .into_raw()
2001}
2002
2003#[no_mangle]
2004pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthToken_getTokenType0(
2005    mut env: JNIEnv,
2006    _class: JClass,
2007    ptr: jlong,
2008) -> jstring {
2009    if !check_not_null(&mut env, ptr, "RiOAuthToken") {
2010        return std::ptr::null_mut();
2011    }
2012
2013    let token = unsafe { &*(ptr as *const RiOAuthToken) };
2014    env.new_string(&token.token_type)
2015        .expect("Failed to create string")
2016        .into_raw()
2017}
2018
2019#[no_mangle]
2020pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthToken_getRefreshToken0(
2021    mut env: JNIEnv,
2022    _class: JClass,
2023    ptr: jlong,
2024) -> jstring {
2025    if !check_not_null(&mut env, ptr, "RiOAuthToken") {
2026        return std::ptr::null_mut();
2027    }
2028
2029    let token = unsafe { &*(ptr as *const RiOAuthToken) };
2030    match &token.refresh_token {
2031        Some(rt) => env
2032            .new_string(rt)
2033            .expect("Failed to create string")
2034            .into_raw(),
2035        None => std::ptr::null_mut(),
2036    }
2037}
2038
2039#[no_mangle]
2040pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthToken_getScope0(
2041    mut env: JNIEnv,
2042    _class: JClass,
2043    ptr: jlong,
2044) -> jstring {
2045    if !check_not_null(&mut env, ptr, "RiOAuthToken") {
2046        return std::ptr::null_mut();
2047    }
2048
2049    let token = unsafe { &*(ptr as *const RiOAuthToken) };
2050    match &token.scope {
2051        Some(s) => env
2052            .new_string(s)
2053            .expect("Failed to create string")
2054            .into_raw(),
2055        None => std::ptr::null_mut(),
2056    }
2057}
2058
2059#[no_mangle]
2060pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthToken_getExpiresIn0(
2061    mut env: JNIEnv,
2062    _class: JClass,
2063    ptr: jlong,
2064) -> jlong {
2065    if !check_not_null(&mut env, ptr, "RiOAuthToken") {
2066        return 0;
2067    }
2068
2069    let token = unsafe { &*(ptr as *const RiOAuthToken) };
2070    token.expires_in.unwrap_or(0)
2071}
2072
2073#[no_mangle]
2074pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthToken_free0(
2075    _env: JNIEnv,
2076    _class: JClass,
2077    ptr: jlong,
2078) {
2079    if ptr != 0 {
2080        unsafe {
2081            let _ = Box::from_raw(ptr as *mut RiOAuthToken);
2082        }
2083    }
2084}
2085
2086// =============================================================================
2087// RiOAuthUserInfo JNI Bindings
2088// =============================================================================
2089
2090#[no_mangle]
2091pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthUserInfo_new0(
2092    mut env: JNIEnv,
2093    _class: JClass,
2094    id: JString,
2095    email: JString,
2096    name: JString,
2097    avatar_url: JString,
2098    provider: JString,
2099) -> jlong {
2100    let id_str: String = env.get_string(&id).expect("Failed to get id").into();
2101    let email_str: String = env.get_string(&email).expect("Failed to get email").into();
2102    let name_opt = if name.is_null() {
2103        None
2104    } else {
2105        Some(env.get_string(&name).expect("Failed to get name").into())
2106    };
2107    let avatar_url_opt = if avatar_url.is_null() {
2108        None
2109    } else {
2110        Some(
2111            env.get_string(&avatar_url)
2112                .expect("Failed to get avatar_url")
2113                .into(),
2114        )
2115    };
2116    let provider_str: String = env
2117        .get_string(&provider)
2118        .expect("Failed to get provider")
2119        .into();
2120
2121    let user_info = Box::new(RiOAuthUserInfo {
2122        id: id_str,
2123        email: email_str,
2124        name: name_opt,
2125        avatar_url: avatar_url_opt,
2126        provider: provider_str,
2127    });
2128    Box::into_raw(user_info) as jlong
2129}
2130
2131#[no_mangle]
2132pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthUserInfo_getId0(
2133    mut env: JNIEnv,
2134    _class: JClass,
2135    ptr: jlong,
2136) -> jstring {
2137    if !check_not_null(&mut env, ptr, "RiOAuthUserInfo") {
2138        return std::ptr::null_mut();
2139    }
2140
2141    let user_info = unsafe { &*(ptr as *const RiOAuthUserInfo) };
2142    env.new_string(&user_info.id)
2143        .expect("Failed to create string")
2144        .into_raw()
2145}
2146
2147#[no_mangle]
2148pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthUserInfo_getEmail0(
2149    mut env: JNIEnv,
2150    _class: JClass,
2151    ptr: jlong,
2152) -> jstring {
2153    if !check_not_null(&mut env, ptr, "RiOAuthUserInfo") {
2154        return std::ptr::null_mut();
2155    }
2156
2157    let user_info = unsafe { &*(ptr as *const RiOAuthUserInfo) };
2158    env.new_string(&user_info.email)
2159        .expect("Failed to create string")
2160        .into_raw()
2161}
2162
2163#[no_mangle]
2164pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthUserInfo_getName0(
2165    mut env: JNIEnv,
2166    _class: JClass,
2167    ptr: jlong,
2168) -> jstring {
2169    if !check_not_null(&mut env, ptr, "RiOAuthUserInfo") {
2170        return std::ptr::null_mut();
2171    }
2172
2173    let user_info = unsafe { &*(ptr as *const RiOAuthUserInfo) };
2174    match &user_info.name {
2175        Some(n) => env
2176            .new_string(n)
2177            .expect("Failed to create string")
2178            .into_raw(),
2179        None => std::ptr::null_mut(),
2180    }
2181}
2182
2183#[no_mangle]
2184pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthUserInfo_getAvatarUrl0(
2185    mut env: JNIEnv,
2186    _class: JClass,
2187    ptr: jlong,
2188) -> jstring {
2189    if !check_not_null(&mut env, ptr, "RiOAuthUserInfo") {
2190        return std::ptr::null_mut();
2191    }
2192
2193    let user_info = unsafe { &*(ptr as *const RiOAuthUserInfo) };
2194    match &user_info.avatar_url {
2195        Some(url) => env
2196            .new_string(url)
2197            .expect("Failed to create string")
2198            .into_raw(),
2199        None => std::ptr::null_mut(),
2200    }
2201}
2202
2203#[no_mangle]
2204pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthUserInfo_getProvider0(
2205    mut env: JNIEnv,
2206    _class: JClass,
2207    ptr: jlong,
2208) -> jstring {
2209    if !check_not_null(&mut env, ptr, "RiOAuthUserInfo") {
2210        return std::ptr::null_mut();
2211    }
2212
2213    let user_info = unsafe { &*(ptr as *const RiOAuthUserInfo) };
2214    env.new_string(&user_info.provider)
2215        .expect("Failed to create string")
2216        .into_raw()
2217}
2218
2219#[no_mangle]
2220pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthUserInfo_free0(
2221    _env: JNIEnv,
2222    _class: JClass,
2223    ptr: jlong,
2224) {
2225    if ptr != 0 {
2226        unsafe {
2227            let _ = Box::from_raw(ptr as *mut RiOAuthUserInfo);
2228        }
2229    }
2230}
2231
2232// =============================================================================
2233// RiOAuthManager JNI Bindings
2234// =============================================================================
2235
2236#[no_mangle]
2237pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthManager_new0(
2238    _env: JNIEnv,
2239    _class: JClass,
2240) -> jlong {
2241    use crate::cache::RiMemoryCache;
2242    use std::sync::Arc;
2243
2244    let cache = Arc::new(RiMemoryCache::new());
2245    let manager = Box::new(RiOAuthManager::new(cache));
2246    Box::into_raw(manager) as jlong
2247}
2248
2249#[no_mangle]
2250pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthManager_registerProvider0(
2251    mut env: JNIEnv,
2252    _class: JClass,
2253    ptr: jlong,
2254    provider_ptr: jlong,
2255) {
2256    if !check_not_null(&mut env, ptr, "RiOAuthManager") {
2257        return;
2258    }
2259    if !check_not_null(&mut env, provider_ptr, "RiOAuthProvider") {
2260        return;
2261    }
2262
2263    let manager = unsafe { &*(ptr as *const RiOAuthManager) };
2264    let provider = unsafe { &*(provider_ptr as *const RiOAuthProvider) };
2265
2266    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
2267    let _ = rt.block_on(async { manager.register_provider(provider.clone()).await });
2268}
2269
2270#[no_mangle]
2271pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthManager_getProvider0(
2272    mut env: JNIEnv,
2273    _class: JClass,
2274    ptr: jlong,
2275    provider_id: JString,
2276) -> jlong {
2277    if !check_not_null(&mut env, ptr, "RiOAuthManager") {
2278        return 0;
2279    }
2280
2281    let manager = unsafe { &*(ptr as *const RiOAuthManager) };
2282    let provider_id_str: String = env
2283        .get_string(&provider_id)
2284        .expect("Failed to get provider_id")
2285        .into();
2286
2287    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
2288    match rt.block_on(async { manager.get_provider(&provider_id_str).await }) {
2289        Ok(Some(provider)) => {
2290            let provider_box = Box::new(provider);
2291            Box::into_raw(provider_box) as jlong
2292        }
2293        _ => 0,
2294    }
2295}
2296
2297#[no_mangle]
2298pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthManager_getAuthUrl0(
2299    mut env: JNIEnv,
2300    _class: JClass,
2301    ptr: jlong,
2302    provider_id: JString,
2303    state: JString,
2304) -> jstring {
2305    if !check_not_null(&mut env, ptr, "RiOAuthManager") {
2306        return std::ptr::null_mut();
2307    }
2308
2309    let manager = unsafe { &*(ptr as *const RiOAuthManager) };
2310    let provider_id_str: String = env
2311        .get_string(&provider_id)
2312        .expect("Failed to get provider_id")
2313        .into();
2314    let state_str: String = env.get_string(&state).expect("Failed to get state").into();
2315
2316    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
2317    match rt.block_on(async { manager.get_auth_url(&provider_id_str, &state_str).await }) {
2318        Ok(Some(url)) => env
2319            .new_string(&url)
2320            .expect("Failed to create string")
2321            .into_raw(),
2322        _ => std::ptr::null_mut(),
2323    }
2324}
2325
2326#[no_mangle]
2327pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthManager_exchangeCodeForToken0(
2328    mut env: JNIEnv,
2329    _class: JClass,
2330    ptr: jlong,
2331    provider_id: JString,
2332    code: JString,
2333    redirect_uri: JString,
2334) -> jlong {
2335    if !check_not_null(&mut env, ptr, "RiOAuthManager") {
2336        return 0;
2337    }
2338
2339    let manager = unsafe { &*(ptr as *const RiOAuthManager) };
2340    let provider_id_str: String = env
2341        .get_string(&provider_id)
2342        .expect("Failed to get provider_id")
2343        .into();
2344    let code_str: String = env.get_string(&code).expect("Failed to get code").into();
2345    let redirect_uri_str: String = env
2346        .get_string(&redirect_uri)
2347        .expect("Failed to get redirect_uri")
2348        .into();
2349
2350    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
2351    match rt.block_on(async {
2352        manager
2353            .exchange_code_for_token(&provider_id_str, &code_str, &redirect_uri_str)
2354            .await
2355    }) {
2356        Ok(Some(token)) => {
2357            let token_box = Box::new(token);
2358            Box::into_raw(token_box) as jlong
2359        }
2360        _ => 0,
2361    }
2362}
2363
2364#[no_mangle]
2365pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthManager_getUserInfo0(
2366    mut env: JNIEnv,
2367    _class: JClass,
2368    ptr: jlong,
2369    provider_id: JString,
2370    access_token: JString,
2371) -> jlong {
2372    if !check_not_null(&mut env, ptr, "RiOAuthManager") {
2373        return 0;
2374    }
2375
2376    let manager = unsafe { &*(ptr as *const RiOAuthManager) };
2377    let provider_id_str: String = env
2378        .get_string(&provider_id)
2379        .expect("Failed to get provider_id")
2380        .into();
2381    let access_token_str: String = env
2382        .get_string(&access_token)
2383        .expect("Failed to get access_token")
2384        .into();
2385
2386    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
2387    match rt.block_on(async {
2388        manager
2389            .get_user_info(&provider_id_str, &access_token_str)
2390            .await
2391    }) {
2392        Ok(Some(user_info)) => {
2393            let user_info_box = Box::new(user_info);
2394            Box::into_raw(user_info_box) as jlong
2395        }
2396        _ => 0,
2397    }
2398}
2399
2400#[no_mangle]
2401pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthManager_refreshToken0(
2402    mut env: JNIEnv,
2403    _class: JClass,
2404    ptr: jlong,
2405    provider_id: JString,
2406    refresh_token: JString,
2407) -> jlong {
2408    if !check_not_null(&mut env, ptr, "RiOAuthManager") {
2409        return 0;
2410    }
2411
2412    let manager = unsafe { &*(ptr as *const RiOAuthManager) };
2413    let provider_id_str: String = env
2414        .get_string(&provider_id)
2415        .expect("Failed to get provider_id")
2416        .into();
2417    let refresh_token_str: String = env
2418        .get_string(&refresh_token)
2419        .expect("Failed to get refresh_token")
2420        .into();
2421
2422    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
2423    match rt.block_on(async {
2424        manager
2425            .refresh_token(&provider_id_str, &refresh_token_str)
2426            .await
2427    }) {
2428        Ok(Some(token)) => {
2429            let token_box = Box::new(token);
2430            Box::into_raw(token_box) as jlong
2431        }
2432        _ => 0,
2433    }
2434}
2435
2436#[no_mangle]
2437pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthManager_revokeToken0(
2438    mut env: JNIEnv,
2439    _class: JClass,
2440    ptr: jlong,
2441    provider_id: JString,
2442    access_token: JString,
2443) -> jboolean {
2444    if !check_not_null(&mut env, ptr, "RiOAuthManager") {
2445        return 0;
2446    }
2447
2448    let manager = unsafe { &*(ptr as *const RiOAuthManager) };
2449    let provider_id_str: String = env
2450        .get_string(&provider_id)
2451        .expect("Failed to get provider_id")
2452        .into();
2453    let access_token_str: String = env
2454        .get_string(&access_token)
2455        .expect("Failed to get access_token")
2456        .into();
2457
2458    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
2459    match rt.block_on(async {
2460        manager
2461            .revoke_token(&provider_id_str, &access_token_str)
2462            .await
2463    }) {
2464        Ok(result) => {
2465            if result {
2466                1
2467            } else {
2468                0
2469            }
2470        }
2471        Err(_) => 0,
2472    }
2473}
2474
2475#[no_mangle]
2476pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthManager_listProviders0(
2477    mut env: JNIEnv,
2478    _class: JClass,
2479    ptr: jlong,
2480) -> jlongArray {
2481    if !check_not_null(&mut env, ptr, "RiOAuthManager") {
2482        return std::ptr::null_mut();
2483    }
2484
2485    let manager = unsafe { &*(ptr as *const RiOAuthManager) };
2486
2487    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
2488    let providers = rt
2489        .block_on(async { manager.list_providers().await })
2490        .unwrap_or_default();
2491
2492    let ptrs: Vec<jlong> = providers
2493        .into_iter()
2494        .map(|p| Box::into_raw(Box::new(p)) as jlong)
2495        .collect();
2496
2497    let array = env
2498        .new_long_array(ptrs.len() as jint)
2499        .expect("Failed to create array");
2500    env.set_long_array_region(&array, 0, &ptrs)
2501        .expect("Failed to set array");
2502
2503    array.into_raw()
2504}
2505
2506#[no_mangle]
2507pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthManager_disableProvider0(
2508    mut env: JNIEnv,
2509    _class: JClass,
2510    ptr: jlong,
2511    provider_id: JString,
2512) -> jboolean {
2513    if !check_not_null(&mut env, ptr, "RiOAuthManager") {
2514        return 0;
2515    }
2516
2517    let manager = unsafe { &*(ptr as *const RiOAuthManager) };
2518    let provider_id_str: String = env
2519        .get_string(&provider_id)
2520        .expect("Failed to get provider_id")
2521        .into();
2522
2523    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
2524    match rt.block_on(async { manager.disable_provider(&provider_id_str).await }) {
2525        Ok(result) => {
2526            if result {
2527                1
2528            } else {
2529                0
2530            }
2531        }
2532        Err(_) => 0,
2533    }
2534}
2535
2536#[no_mangle]
2537pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthManager_enableProvider0(
2538    mut env: JNIEnv,
2539    _class: JClass,
2540    ptr: jlong,
2541    provider_id: JString,
2542) -> jboolean {
2543    if !check_not_null(&mut env, ptr, "RiOAuthManager") {
2544        return 0;
2545    }
2546
2547    let manager = unsafe { &*(ptr as *const RiOAuthManager) };
2548    let provider_id_str: String = env
2549        .get_string(&provider_id)
2550        .expect("Failed to get provider_id")
2551        .into();
2552
2553    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
2554    match rt.block_on(async { manager.enable_provider(&provider_id_str).await }) {
2555        Ok(result) => {
2556            if result {
2557                1
2558            } else {
2559                0
2560            }
2561        }
2562        Err(_) => 0,
2563    }
2564}
2565
2566#[no_mangle]
2567pub extern "system" fn Java_com_dunimd_ri_auth_RiOAuthManager_free0(
2568    _env: JNIEnv,
2569    _class: JClass,
2570    ptr: jlong,
2571) {
2572    if ptr != 0 {
2573        unsafe {
2574            let _ = Box::from_raw(ptr as *mut RiOAuthManager);
2575        }
2576    }
2577}
2578
2579// =============================================================================
2580// RiRevokedTokenInfo JNI Bindings
2581// =============================================================================
2582
2583#[no_mangle]
2584pub extern "system" fn Java_com_dunimd_ri_auth_RiRevokedTokenInfo_new0(
2585    mut env: JNIEnv,
2586    _class: JClass,
2587    token_id: JString,
2588    user_id: JString,
2589    revoked_at: jlong,
2590    expires_at: jlong,
2591    reason: JString,
2592) -> jlong {
2593    let token_id_str: String = env
2594        .get_string(&token_id)
2595        .expect("Failed to get token_id")
2596        .into();
2597    let user_id_str: String = env
2598        .get_string(&user_id)
2599        .expect("Failed to get user_id")
2600        .into();
2601    let reason_opt = if reason.is_null() {
2602        None
2603    } else {
2604        Some(
2605            env.get_string(&reason)
2606                .expect("Failed to get reason")
2607                .into(),
2608        )
2609    };
2610
2611    let info = Box::new(RiRevokedTokenInfo {
2612        token_id: token_id_str,
2613        user_id: user_id_str,
2614        revoked_at: revoked_at as u64,
2615        expires_at: expires_at as u64,
2616        reason: reason_opt,
2617    });
2618    Box::into_raw(info) as jlong
2619}
2620
2621#[no_mangle]
2622pub extern "system" fn Java_com_dunimd_ri_auth_RiRevokedTokenInfo_getTokenId0(
2623    mut env: JNIEnv,
2624    _class: JClass,
2625    ptr: jlong,
2626) -> jstring {
2627    if !check_not_null(&mut env, ptr, "RiRevokedTokenInfo") {
2628        return std::ptr::null_mut();
2629    }
2630
2631    let info = unsafe { &*(ptr as *const RiRevokedTokenInfo) };
2632    env.new_string(&info.token_id)
2633        .expect("Failed to create string")
2634        .into_raw()
2635}
2636
2637#[no_mangle]
2638pub extern "system" fn Java_com_dunimd_ri_auth_RiRevokedTokenInfo_getUserId0(
2639    mut env: JNIEnv,
2640    _class: JClass,
2641    ptr: jlong,
2642) -> jstring {
2643    if !check_not_null(&mut env, ptr, "RiRevokedTokenInfo") {
2644        return std::ptr::null_mut();
2645    }
2646
2647    let info = unsafe { &*(ptr as *const RiRevokedTokenInfo) };
2648    env.new_string(&info.user_id)
2649        .expect("Failed to create string")
2650        .into_raw()
2651}
2652
2653#[no_mangle]
2654pub extern "system" fn Java_com_dunimd_ri_auth_RiRevokedTokenInfo_getRevokedAt0(
2655    mut env: JNIEnv,
2656    _class: JClass,
2657    ptr: jlong,
2658) -> jlong {
2659    if !check_not_null(&mut env, ptr, "RiRevokedTokenInfo") {
2660        return 0;
2661    }
2662
2663    let info = unsafe { &*(ptr as *const RiRevokedTokenInfo) };
2664    info.revoked_at as jlong
2665}
2666
2667#[no_mangle]
2668pub extern "system" fn Java_com_dunimd_ri_auth_RiRevokedTokenInfo_getExpiresAt0(
2669    mut env: JNIEnv,
2670    _class: JClass,
2671    ptr: jlong,
2672) -> jlong {
2673    if !check_not_null(&mut env, ptr, "RiRevokedTokenInfo") {
2674        return 0;
2675    }
2676
2677    let info = unsafe { &*(ptr as *const RiRevokedTokenInfo) };
2678    info.expires_at as jlong
2679}
2680
2681#[no_mangle]
2682pub extern "system" fn Java_com_dunimd_ri_auth_RiRevokedTokenInfo_getReason0(
2683    mut env: JNIEnv,
2684    _class: JClass,
2685    ptr: jlong,
2686) -> jstring {
2687    if !check_not_null(&mut env, ptr, "RiRevokedTokenInfo") {
2688        return std::ptr::null_mut();
2689    }
2690
2691    let info = unsafe { &*(ptr as *const RiRevokedTokenInfo) };
2692    match &info.reason {
2693        Some(r) => env
2694            .new_string(r)
2695            .expect("Failed to create string")
2696            .into_raw(),
2697        None => std::ptr::null_mut(),
2698    }
2699}
2700
2701#[no_mangle]
2702pub extern "system" fn Java_com_dunimd_ri_auth_RiRevokedTokenInfo_free0(
2703    _env: JNIEnv,
2704    _class: JClass,
2705    ptr: jlong,
2706) {
2707    if ptr != 0 {
2708        unsafe {
2709            let _ = Box::from_raw(ptr as *mut RiRevokedTokenInfo);
2710        }
2711    }
2712}
2713
2714// =============================================================================
2715// RiJWTRevocationList JNI Bindings
2716// =============================================================================
2717
2718#[no_mangle]
2719pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTRevocationList_new0(
2720    _env: JNIEnv,
2721    _class: JClass,
2722) -> jlong {
2723    let list = Box::new(RiJWTRevocationList::new());
2724    Box::into_raw(list) as jlong
2725}
2726
2727#[no_mangle]
2728pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTRevocationList_revokeToken0(
2729    mut env: JNIEnv,
2730    _class: JClass,
2731    ptr: jlong,
2732    token: JString,
2733    user_id: JString,
2734    reason: JString,
2735    ttl_secs: jlong,
2736) {
2737    if !check_not_null(&mut env, ptr, "RiJWTRevocationList") {
2738        return;
2739    }
2740
2741    let list = unsafe { &*(ptr as *const RiJWTRevocationList) };
2742    let token_str: String = env.get_string(&token).expect("Failed to get token").into();
2743    let user_id_str: String = env
2744        .get_string(&user_id)
2745        .expect("Failed to get user_id")
2746        .into();
2747    let reason_opt = if reason.is_null() {
2748        None
2749    } else {
2750        Some(
2751            env.get_string(&reason)
2752                .expect("Failed to get reason")
2753                .into(),
2754        )
2755    };
2756
2757    list.revoke_token(&token_str, &user_id_str, reason_opt, ttl_secs as u64);
2758}
2759
2760#[no_mangle]
2761pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTRevocationList_isRevoked0(
2762    mut env: JNIEnv,
2763    _class: JClass,
2764    ptr: jlong,
2765    token: JString,
2766) -> jboolean {
2767    if !check_not_null(&mut env, ptr, "RiJWTRevocationList") {
2768        return 0;
2769    }
2770
2771    let list = unsafe { &*(ptr as *const RiJWTRevocationList) };
2772    let token_str: String = env.get_string(&token).expect("Failed to get token").into();
2773
2774    if list.is_revoked(&token_str) {
2775        1
2776    } else {
2777        0
2778    }
2779}
2780
2781#[no_mangle]
2782pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTRevocationList_revokeByUser0(
2783    mut env: JNIEnv,
2784    _class: JClass,
2785    ptr: jlong,
2786    user_id: JString,
2787) -> jboolean {
2788    if !check_not_null(&mut env, ptr, "RiJWTRevocationList") {
2789        return 0;
2790    }
2791
2792    let list = unsafe { &*(ptr as *const RiJWTRevocationList) };
2793    let user_id_str: String = env
2794        .get_string(&user_id)
2795        .expect("Failed to get user_id")
2796        .into();
2797
2798    let count = list.revoke_all_user_tokens(&user_id_str, None);
2799    if count > 0 {
2800        1
2801    } else {
2802        0
2803    }
2804}
2805
2806#[no_mangle]
2807pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTRevocationList_getRevocationInfo0(
2808    mut env: JNIEnv,
2809    _class: JClass,
2810    ptr: jlong,
2811    token: JString,
2812) -> jlong {
2813    if !check_not_null(&mut env, ptr, "RiJWTRevocationList") {
2814        return 0;
2815    }
2816
2817    let list = unsafe { &*(ptr as *const RiJWTRevocationList) };
2818    let token_str: String = env.get_string(&token).expect("Failed to get token").into();
2819
2820    match list.get_revocation_info(&token_str) {
2821        Some(info) => {
2822            let info_box = Box::new(info);
2823            Box::into_raw(info_box) as jlong
2824        }
2825        None => 0,
2826    }
2827}
2828
2829#[no_mangle]
2830pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTRevocationList_getRevokedCount0(
2831    mut env: JNIEnv,
2832    _class: JClass,
2833    ptr: jlong,
2834) -> jint {
2835    if !check_not_null(&mut env, ptr, "RiJWTRevocationList") {
2836        return 0;
2837    }
2838
2839    let list = unsafe { &*(ptr as *const RiJWTRevocationList) };
2840    list.get_revoked_count() as jint
2841}
2842
2843#[no_mangle]
2844pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTRevocationList_cleanup0(
2845    mut env: JNIEnv,
2846    _class: JClass,
2847    ptr: jlong,
2848) -> jint {
2849    if !check_not_null(&mut env, ptr, "RiJWTRevocationList") {
2850        return 0;
2851    }
2852
2853    let list = unsafe { &*(ptr as *const RiJWTRevocationList) };
2854
2855    let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
2856    let count = rt.block_on(async { list.cleanup_expired() });
2857
2858    count as jint
2859}
2860
2861#[no_mangle]
2862pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTRevocationList_clear0(
2863    mut env: JNIEnv,
2864    _class: JClass,
2865    ptr: jlong,
2866) {
2867    if !check_not_null(&mut env, ptr, "RiJWTRevocationList") {
2868        return;
2869    }
2870
2871    let list = unsafe { &*(ptr as *const RiJWTRevocationList) };
2872    list.clear();
2873}
2874
2875#[no_mangle]
2876pub extern "system" fn Java_com_dunimd_ri_auth_RiJWTRevocationList_free0(
2877    _env: JNIEnv,
2878    _class: JClass,
2879    ptr: jlong,
2880) {
2881    if ptr != 0 {
2882        unsafe {
2883            let _ = Box::from_raw(ptr as *mut RiJWTRevocationList);
2884        }
2885    }
2886}
2887
2888// =============================================================================
2889// RiSecurityManager JNI Bindings (Static Methods)
2890// =============================================================================
2891
2892#[no_mangle]
2893pub extern "system" fn Java_com_dunimd_ri_auth_RiSecurityManager_encrypt0(
2894    mut env: JNIEnv,
2895    _class: JClass,
2896    plaintext: JString,
2897) -> jstring {
2898    let plaintext_str: String = env
2899        .get_string(&plaintext)
2900        .expect("Failed to get plaintext")
2901        .into();
2902
2903    match RiSecurityManager::encrypt(&plaintext_str) {
2904        Ok(encrypted) => env
2905            .new_string(&encrypted)
2906            .expect("Failed to create string")
2907            .into_raw(),
2908        Err(_) => std::ptr::null_mut(),
2909    }
2910}
2911
2912#[no_mangle]
2913pub extern "system" fn Java_com_dunimd_ri_auth_RiSecurityManager_decrypt0(
2914    mut env: JNIEnv,
2915    _class: JClass,
2916    encrypted: JString,
2917) -> jstring {
2918    let encrypted_str: String = env
2919        .get_string(&encrypted)
2920        .expect("Failed to get encrypted")
2921        .into();
2922
2923    match RiSecurityManager::decrypt(&encrypted_str) {
2924        Ok(decrypted) => env
2925            .new_string(&decrypted)
2926            .expect("Failed to create string")
2927            .into_raw(),
2928        Err(_) => std::ptr::null_mut(),
2929    }
2930}
2931
2932#[no_mangle]
2933pub extern "system" fn Java_com_dunimd_ri_auth_RiSecurityManager_hmacSign0(
2934    mut env: JNIEnv,
2935    _class: JClass,
2936    data: JString,
2937) -> jstring {
2938    let data_str: String = env.get_string(&data).expect("Failed to get data").into();
2939
2940    let signature = RiSecurityManager::hmac_sign(&data_str);
2941    env.new_string(&signature)
2942        .expect("Failed to create string")
2943        .into_raw()
2944}
2945
2946#[no_mangle]
2947pub extern "system" fn Java_com_dunimd_ri_auth_RiSecurityManager_hmacVerify0(
2948    mut env: JNIEnv,
2949    _class: JClass,
2950    data: JString,
2951    signature: JString,
2952) -> jboolean {
2953    let data_str: String = env.get_string(&data).expect("Failed to get data").into();
2954    let signature_str: String = env
2955        .get_string(&signature)
2956        .expect("Failed to get signature")
2957        .into();
2958
2959    if RiSecurityManager::hmac_verify(&data_str, &signature_str) {
2960        1
2961    } else {
2962        0
2963    }
2964}
2965
2966#[no_mangle]
2967pub extern "system" fn Java_com_dunimd_ri_auth_RiSecurityManager_generateEncryptionKey0(
2968    mut env: JNIEnv,
2969    _class: JClass,
2970) -> jstring {
2971    let key = RiSecurityManager::generate_encryption_key();
2972    env.new_string(&key)
2973        .expect("Failed to create string")
2974        .into_raw()
2975}
2976
2977#[no_mangle]
2978pub extern "system" fn Java_com_dunimd_ri_auth_RiSecurityManager_generateHmacKey0(
2979    mut env: JNIEnv,
2980    _class: JClass,
2981) -> jstring {
2982    let key = RiSecurityManager::generate_hmac_key();
2983    env.new_string(&key)
2984        .expect("Failed to create string")
2985        .into_raw()
2986}