csharp-sdk-upm/Engine/Controllers/LCClassHookController.cs

83 lines
3.2 KiB
C#

using System;
using System.Text.Json;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Cors;
using LeanCloud.Storage.Internal.Object;
using LeanCloud.Storage;
namespace LeanCloud.Engine {
[ApiController]
[Route("{1,1.1}")]
[EnableCors(LCEngine.LCEngineCORS)]
public class LCClassHookController : ControllerBase {
private Dictionary<string, MethodInfo> ClassHooks => LCEngine.ClassHooks;
[HttpPost("functions/{className}/{hookName}")]
public async Task<object> Hook(string className, string hookName, JsonElement body) {
try {
LCLogger.Debug($"Hook: {className}#{hookName}");
LCLogger.Debug(body.ToString());
LCEngine.CheckHookKey(Request);
string classHookName = GetClassHookName(className, hookName);
if (ClassHooks.TryGetValue(classHookName, out MethodInfo mi)) {
Dictionary<string, object> data = LCEngine.Decode(body);
LCObjectData objectData = LCObjectData.Decode(data["object"] as Dictionary<string, object>);
objectData.ClassName = className;
LCObject obj = LCObject.Create(className);
obj.Merge(objectData);
// 避免死循环
if (hookName.StartsWith("before")) {
obj.DisableBeforeHook();
} else {
obj.DisableAfterHook();
}
LCEngine.InitRequestContext(Request);
LCUser user = null;
if (data.TryGetValue("user", out object userObj) &&
userObj != null) {
user = new LCUser();
user.Merge(LCObjectData.Decode(userObj as Dictionary<string, object>));
LCEngineRequestContext.CurrentUser = user;
}
LCObject result = await LCEngine.Invoke(mi, new object[] { obj }) as LCObject;
if (result != null) {
return LCCloud.Encode(result);
}
}
return body;
} catch (Exception e) {
return StatusCode(500, e.Message);
}
}
private static string GetClassHookName(string className, string hookName) {
switch (hookName) {
case "beforeSave":
return $"__before_save_for_{className}";
case "afterSave":
return $"__after_save_for_{className}";
case "beforeUpdate":
return $"__before_update_for_{className}";
case "afterUpdate":
return $"__after_update_for_{className}";
case "beforeDelete":
return $"__before_delete_for_{className}";
case "afterDelete":
return $"__after_delete_for_{className}";
default:
throw new Exception($"Error hook name: {hookName}");
}
}
}
}