From e7193933ae3f0e6c6d7019d3f9ff7538c5d4f793 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Tue, 12 May 2026 18:37:23 +0800 Subject: [PATCH] fix: ensure user and org are created in users table before apikey creation in usersync --- wwwroot/usersync/index.dspy | 232 +++++++++++------------------------- 1 file changed, 70 insertions(+), 162 deletions(-) diff --git a/wwwroot/usersync/index.dspy b/wwwroot/usersync/index.dspy index 09b6cdc..1e8be8f 100644 --- a/wwwroot/usersync/index.dspy +++ b/wwwroot/usersync/index.dspy @@ -1,32 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -"""用户同步接口 - POST方式同步单个或批量用户到dapi模块并返回apikey - -POST /rbac/usersync/ - -请求体示例(单个用户): -{ - "action": "single", - "dappid": "myapp", - "user": { - "id": "user123", - "orgid": "org456", - "username": "testuser", - "name": "测试用户", - "email": "test@example.com" - } -} - -请求体示例(批量用户): -{ - "action": "batch", - "dappid": "myapp", - "users": [ - {"id": "user1", "orgid": "org1", "username": "user1"}, - {"id": "user2", "orgid": "org1", "username": "user2"} - ] -} -""" +"""用户同步接口 - POST方式同步单个或批量用户到dapi模块并返回apikey""" +from datetime import datetime # 获取参数 action = params_kw.get('action', 'batch') @@ -48,9 +23,7 @@ create_apikey_func = create_user_apikey async with db.sqlorContext(dbname) as sor: if action == 'single': - # 单个用户同步 user_data = params_kw.get('user', {}) - user_id = user_data.get('id', '') user_orgid = user_data.get('orgid', '') @@ -60,172 +33,107 @@ async with db.sqlorContext(dbname) as sor: 'message': 'user.id和user.orgid参数必填' }, ensure_ascii=False) - # 如果dapi模块提供了create_user_apikey函数,直接调用 + # 确保机构存在 + org = await sor.R('organization', {'id': user_orgid}) + if not org: + await sor.C('organization', {'id': user_orgid, 'orgname': user_data.get('name', user_data.get('username', user_id))}) + await sor.C('orgtypes', {'id': getID(), 'orgid': user_orgid, 'orgtypeid': 'customer'}) + + # 确保用户存在 + usr = await sor.R('users', {'id': user_id}) + if not usr: + await sor.C('users', { + 'id': user_id, + 'orgid': user_orgid, + 'username': user_data.get('username', user_id), + 'name': user_data.get('name', ''), + 'email': user_data.get('email', ''), + 'password': password_encode(user_data.get('password', '111111')) + }) + + # 创建apikey if create_apikey_func: - result = await create_user_apikey( - sor, - dappid, - user_id, - user_orgid, + result = await create_apikey_func( + sor, dappid, user_id, user_orgid, **{k: v for k, v in user_data.items() if k not in ['id', 'orgid']} ) return json.dumps(result, ensure_ascii=False) - # 否则自己创建apikey - # 检查apikey是否已存在 - existing = await sor.R('downapikey', { - 'dappid': dappid, - 'duserid': user_id, - 'dorgid': user_orgid - }) - + # 手动创建apikey + existing = await sor.R('downapikey', {'dappid': dappid, 'duserid': user_id, 'dorgid': user_orgid}) if existing: - # 验证用户是否存在 - user_check = await sor.R('users', {'id': existing[0].userid}) - if not user_check: - # 脏数据:downapikey 存在但用户已删除,清理后重新创建 - await sor.D('downapikey', {'id': existing[0].id}) - existing = None - else: - apikey = password_decode(existing[0].apikey) - return json.dumps({ - 'status': 'success', - 'data': [{ - 'user_id': user_id, - 'username': user_data.get('username', ''), - 'apikey': apikey, - 'status': 'existing' - }] - }, ensure_ascii=False) + f = get_serverenv('password_decode') + apikey = f(existing[0].apikey) + return json.dumps({'status': 'success', 'data': [{'user_id': user_id, 'apikey': apikey, 'status': 'existing'}]}, ensure_ascii=False) - # 创建新apikey apikey_id = getID() apikey_value = getID() - ns = { - 'id': apikey_id, - 'dappid': dappid, - 'dorgid': user_orgid, - 'duserid': user_id, - 'orgid': user_orgid, - 'userid': user_id, - 'apikey': password_encode(apikey_value), - 'enabled': '1', - 'created_at': datetime.now().strftime('%Y-%m-%d'), - 'expired_date': '9999-12-31' + 'id': apikey_id, 'dappid': dappid, 'dorgid': user_orgid, 'duserid': user_id, + 'orgid': user_orgid, 'userid': user_id, 'apikey': password_encode(apikey_value), + 'enabled': '1', 'created_at': datetime.now().strftime('%Y-%m-%d'), 'expired_date': '9999-12-31' } - await sor.C('downapikey', ns) - - return json.dumps({ - 'status': 'success', - 'data': [{ - 'user_id': user_id, - 'username': user_data.get('username', ''), - 'apikey': apikey_value, - 'status': 'created' - }] - }, ensure_ascii=False) + return json.dumps({'status': 'success', 'data': [{'user_id': user_id, 'apikey': apikey_value, 'status': 'created'}]}, ensure_ascii=False) elif action == 'batch': - # 批量用户同步 users_list = params_kw.get('users', []) if not users_list: - return json.dumps({ - 'status': 'error', - 'message': 'users参数必填(用户对象数组)' - }, ensure_ascii=False) + return json.dumps({'status': 'error', 'message': 'users参数必填(用户对象数组)'}, ensure_ascii=False) result_data = [] - for user_data in users_list: user_id = user_data.get('id', '') user_orgid = user_data.get('orgid', '') if not user_id or not user_orgid: - result_data.append({ - 'user_id': user_id, - 'status': 'error', - 'message': 'user.id和user.orgid必填' - }) + result_data.append({'user_id': user_id, 'status': 'error', 'message': 'user.id和user.orgid必填'}) continue - # 如果dapi模块提供了create_user_apikey函数,直接调用 + # 确保机构存在 + org = await sor.R('organization', {'id': user_orgid}) + if not org: + await sor.C('organization', {'id': user_orgid, 'orgname': user_data.get('name', user_data.get('username', user_id))}) + await sor.C('orgtypes', {'id': getID(), 'orgid': user_orgid, 'orgtypeid': 'customer'}) + + # 确保用户存在 + usr = await sor.R('users', {'id': user_id}) + if not usr: + await sor.C('users', { + 'id': user_id, 'orgid': user_orgid, + 'username': user_data.get('username', user_id), 'name': user_data.get('name', ''), + 'email': user_data.get('email', ''), 'password': password_encode(user_data.get('password', '111111')) + }) + + # 创建apikey if create_apikey_func: - result = await create_user_apikey( - sor, - dappid, - user_id, - user_orgid, + result = await create_apikey_func( + sor, dappid, user_id, user_orgid, **{k: v for k, v in user_data.items() if k not in ['id', 'orgid']} ) - result_data.append({ - 'user_id': user_id, - 'username': user_data.get('username', ''), - 'apikey': result.get('apikey', ''), - 'status': result.get('message', 'created'), + 'user_id': user_id, 'username': user_data.get('username', ''), + 'apikey': result.get('apikey', ''), 'status': result.get('message', 'created'), 'result_status': result.get('status') }) else: - # 检查apikey是否已存在 - existing = await sor.R('downapikey', { - 'dappid': dappid, - 'duserid': user_id, - 'dorgid': user_orgid - }) - + existing = await sor.R('downapikey', {'dappid': dappid, 'duserid': user_id, 'dorgid': user_orgid}) if existing: - # 验证用户是否存在 - user_check = await sor.R('users', {'id': existing[0].userid}) - if not user_check: - # 脏数据,清理后重新创建 - await sor.D('downapikey', {'id': existing[0].id}) - existing = None - else: - apikey = password_decode(existing[0].apikey) - result_data.append({ - 'user_id': user_id, - 'username': user_data.get('username', ''), - 'apikey': apikey, - 'status': 'existing' - }) - continue - - # 创建新apikey - apikey_id = getID() - apikey_value = getID() - - ns = { - 'id': apikey_id, - 'dappid': dappid, - 'dorgid': user_orgid, - 'duserid': user_id, - 'orgid': user_orgid, - 'userid': user_id, - 'apikey': password_encode(apikey_value), - 'enabled': '1', - 'created_at': datetime.now().strftime('%Y-%m-%d'), - 'expired_date': '9999-12-31' - } - - await sor.C('downapikey', ns) - - result_data.append({ - 'user_id': user_id, - 'username': user_data.get('username', ''), - 'apikey': apikey_value, - 'status': 'created' - }) + f = get_serverenv('password_decode') + apikey = f(existing[0].apikey) + result_data.append({'user_id': user_id, 'apikey': apikey, 'status': 'existing'}) + else: + apikey_id = getID() + apikey_value = getID() + ns = { + 'id': apikey_id, 'dappid': dappid, 'dorgid': user_orgid, 'duserid': user_id, + 'orgid': user_orgid, 'userid': user_id, 'apikey': password_encode(apikey_value), + 'enabled': '1', 'created_at': datetime.now().strftime('%Y-%m-%d'), 'expired_date': '9999-12-31' + } + await sor.C('downapikey', ns) + result_data.append({'user_id': user_id, 'apikey': apikey_value, 'status': 'created'}) - return json.dumps({ - 'status': 'success', - 'data': result_data, - 'total': len(result_data) - }, ensure_ascii=False) + return json.dumps({'status': 'success', 'data': result_data, 'total': len(result_data)}, ensure_ascii=False) else: - return json.dumps({ - 'status': 'error', - 'message': 'action参数必须是single或batch' - }, ensure_ascii=False) + return json.dumps({'status': 'error', 'message': 'action参数必须是single或batch'}, ensure_ascii=False)