mirror of
https://github.com/simtactics/mysimulation.git
synced 2025-07-06 22:50:30 -04:00
Removed NioTSO client and server
- NioTSO client isn't needed because we're using RayLib - Added FreeSO's API server to handle most backend operations
This commit is contained in:
parent
f12ba1502b
commit
22191ce648
591 changed files with 53264 additions and 3362 deletions
157
server/FSO.Server.Api.Core/Controllers/Admin/AdminEventsController.cs
Executable file
157
server/FSO.Server.Api.Core/Controllers/Admin/AdminEventsController.cs
Executable file
|
@ -0,0 +1,157 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using FSO.Server.Api.Core.Models;
|
||||
using FSO.Server.Api.Core.Utils;
|
||||
using FSO.Server.Database.DA.DbEvents;
|
||||
using FSO.Server.Database.DA.Tuning;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
// For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
|
||||
|
||||
namespace FSO.Server.Api.Core.Controllers.Admin
|
||||
{
|
||||
[EnableCors("AdminAppPolicy")]
|
||||
[Route("admin/events")]
|
||||
[ApiController]
|
||||
public class AdminEventsController : ControllerBase
|
||||
{
|
||||
//List events
|
||||
[HttpGet]
|
||||
public IActionResult Get(int limit, int offset, string order)
|
||||
{
|
||||
if (limit == 0) limit = 20;
|
||||
if (order == null) order = "start_day";
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandModerator(Request);
|
||||
using (var da = api.DAFactory.Get())
|
||||
{
|
||||
|
||||
if (limit > 100)
|
||||
{
|
||||
limit = 100;
|
||||
}
|
||||
|
||||
var result = da.Events.All((int)offset, (int)limit, order);
|
||||
return ApiResponse.PagedList<DbEvent>(Request, HttpStatusCode.OK, result);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("presets")]
|
||||
public IActionResult GetPresets()
|
||||
{
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandModerator(Request);
|
||||
using (var da = api.DAFactory.Get())
|
||||
{
|
||||
return new JsonResult(da.Tuning.GetAllPresets().ToList());
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("presets")]
|
||||
public IActionResult CreatePreset([FromBody]PresetCreateModel request)
|
||||
{
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandModerator(Request);
|
||||
using (var da = api.DAFactory.Get())
|
||||
{
|
||||
//make the preset first
|
||||
var preset_id = da.Tuning.CreatePreset(
|
||||
new DbTuningPreset()
|
||||
{
|
||||
name = request.name,
|
||||
description = request.description,
|
||||
flags = request.flags
|
||||
});
|
||||
|
||||
foreach (var item in request.items)
|
||||
{
|
||||
da.Tuning.CreatePresetItem(new DbTuningPresetItem()
|
||||
{
|
||||
preset_id = preset_id,
|
||||
tuning_type = item.tuning_type,
|
||||
tuning_table = item.tuning_table,
|
||||
tuning_index = item.tuning_index,
|
||||
value = item.value
|
||||
});
|
||||
}
|
||||
return new JsonResult(da.Tuning.GetAllPresets().ToList());
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("presets/{preset_id}")]
|
||||
public IActionResult GetPresetEntries(int preset_id)
|
||||
{
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandModerator(Request);
|
||||
using (var da = api.DAFactory.Get())
|
||||
{
|
||||
return new JsonResult(da.Tuning.GetPresetItems(preset_id).ToList());
|
||||
}
|
||||
}
|
||||
|
||||
[HttpDelete("presets/{preset_id}")]
|
||||
public IActionResult DeletePreset(int preset_id)
|
||||
{
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandModerator(Request);
|
||||
using (var da = api.DAFactory.Get())
|
||||
{
|
||||
return da.Tuning.DeletePreset(preset_id) ? (IActionResult)Ok() : NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
// POST admin/updates (start update generation)
|
||||
[HttpPost]
|
||||
public IActionResult Post([FromBody]EventCreateModel request)
|
||||
{
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandModerator(Request);
|
||||
|
||||
using (var da = api.DAFactory.Get())
|
||||
{
|
||||
DbEventType type;
|
||||
try
|
||||
{
|
||||
type = Enum.Parse<DbEventType>(request.type);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return BadRequest("Event type must be one of:" + string.Join(", ", Enum.GetNames(typeof(DbEventType))));
|
||||
}
|
||||
var model = new DbEvent()
|
||||
{
|
||||
title = request.title,
|
||||
description = request.description,
|
||||
start_day = request.start_day,
|
||||
end_day = request.end_day,
|
||||
type = type,
|
||||
value = request.value,
|
||||
value2 = request.value2,
|
||||
mail_subject = request.mail_subject,
|
||||
mail_message = request.mail_message,
|
||||
mail_sender = request.mail_sender,
|
||||
mail_sender_name = request.mail_sender_name
|
||||
};
|
||||
return new JsonResult(new { id = da.Events.Add(model) });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpDelete]
|
||||
[Route("{id}")]
|
||||
public IActionResult Delete(int id)
|
||||
{
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandModerator(Request);
|
||||
|
||||
using (var da = api.DAFactory.Get())
|
||||
{
|
||||
if (!da.Events.Delete(id)) return NotFound();
|
||||
}
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
30
server/FSO.Server.Api.Core/Controllers/Admin/AdminHostsController.cs
Executable file
30
server/FSO.Server.Api.Core/Controllers/Admin/AdminHostsController.cs
Executable file
|
@ -0,0 +1,30 @@
|
|||
using FSO.Server.Api.Core.Utils;
|
||||
using System.Net;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
|
||||
namespace FSO.Server.Api.Core.Controllers.Admin
|
||||
{
|
||||
[EnableCors("AdminAppPolicy")]
|
||||
[Route("admin/hosts")]
|
||||
[ApiController]
|
||||
public class AdminHostsController : ControllerBase
|
||||
{
|
||||
public IActionResult Get()
|
||||
{
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandAdmin(Request);
|
||||
var hosts = api.HostPool.GetAll();
|
||||
|
||||
return ApiResponse.Json(HttpStatusCode.OK, hosts.Select(x => new {
|
||||
role = x.Role,
|
||||
call_sign = x.CallSign,
|
||||
internal_host = x.InternalHost,
|
||||
public_host = x.PublicHost,
|
||||
connected = x.Connected,
|
||||
time_boot = x.BootTime
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
129
server/FSO.Server.Api.Core/Controllers/Admin/AdminOAuthController.cs
Executable file
129
server/FSO.Server.Api.Core/Controllers/Admin/AdminOAuthController.cs
Executable file
|
@ -0,0 +1,129 @@
|
|||
using FSO.Server.Api.Core.Utils;
|
||||
using FSO.Server.Common;
|
||||
using FSO.Server.Servers.Api.JsonWebToken;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FSO.Server.Api.Core.Controllers.Admin
|
||||
{
|
||||
[EnableCors("AdminAppPolicy")]
|
||||
[Route("admin/oauth/token")]
|
||||
[ApiController]
|
||||
public class AdminOAuthController : ControllerBase
|
||||
{
|
||||
[HttpPost]
|
||||
public IActionResult Post([FromForm] AuthRequest auth)
|
||||
{
|
||||
if (auth == null) Ok();
|
||||
if (auth.grant_type == "password")
|
||||
{
|
||||
var api = Api.INSTANCE;
|
||||
using (var da = api.DAFactory.Get())
|
||||
{
|
||||
var user = da.Users.GetByUsername(auth.username);
|
||||
if (user == null || user.is_banned || !(user.is_admin || user.is_moderator))
|
||||
{
|
||||
return ApiResponse.Json(System.Net.HttpStatusCode.OK, new OAuthError
|
||||
{
|
||||
error = "unauthorized_client",
|
||||
error_description = "user_credentials_invalid"
|
||||
});
|
||||
}
|
||||
|
||||
var ip = ApiUtils.GetIP(Request);
|
||||
var accLock = da.Users.GetRemainingAuth(user.user_id, ip);
|
||||
if (accLock != null && (accLock.active || accLock.count >= AuthLoginController.LockAttempts) && accLock.expire_time > Epoch.Now)
|
||||
{
|
||||
return ApiResponse.Json(System.Net.HttpStatusCode.OK, new OAuthError
|
||||
{
|
||||
error = "unauthorized_client",
|
||||
error_description = "account_locked"
|
||||
});
|
||||
}
|
||||
|
||||
var authSettings = da.Users.GetAuthenticationSettings(user.user_id);
|
||||
var isPasswordCorrect = PasswordHasher.Verify(auth.password, new PasswordHash
|
||||
{
|
||||
data = authSettings.data,
|
||||
scheme = authSettings.scheme_class
|
||||
});
|
||||
|
||||
if (!isPasswordCorrect)
|
||||
{
|
||||
var durations = AuthLoginController.LockDuration;
|
||||
var failDelay = 60 * durations[Math.Min(durations.Length - 1, da.Users.FailedConsecutive(user.user_id, ip))];
|
||||
if (accLock == null)
|
||||
{
|
||||
da.Users.NewFailedAuth(user.user_id, ip, (uint)failDelay);
|
||||
}
|
||||
else
|
||||
{
|
||||
var remaining = da.Users.FailedAuth(accLock.attempt_id, (uint)failDelay, AuthLoginController.LockAttempts);
|
||||
}
|
||||
|
||||
return ApiResponse.Json(System.Net.HttpStatusCode.OK, new OAuthError
|
||||
{
|
||||
error = "unauthorized_client",
|
||||
error_description = "user_credentials_invalid"
|
||||
});
|
||||
}
|
||||
|
||||
da.Users.SuccessfulAuth(user.user_id, ip);
|
||||
|
||||
JWTUser identity = new JWTUser();
|
||||
identity.UserName = user.username;
|
||||
var claims = new List<string>();
|
||||
if (user.is_admin || user.is_moderator)
|
||||
{
|
||||
claims.Add("moderator");
|
||||
}
|
||||
if (user.is_admin)
|
||||
{
|
||||
claims.Add("admin");
|
||||
}
|
||||
|
||||
identity.Claims = claims;
|
||||
identity.UserID = user.user_id;
|
||||
|
||||
var token = api.JWT.CreateToken(identity);
|
||||
|
||||
var response = ApiResponse.Json(System.Net.HttpStatusCode.OK, new OAuthSuccess
|
||||
{
|
||||
access_token = token.Token,
|
||||
expires_in = token.ExpiresIn
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
return ApiResponse.Json(System.Net.HttpStatusCode.OK, new OAuthError
|
||||
{
|
||||
error = "invalid_request",
|
||||
error_description = "unknown grant_type"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class OAuthError
|
||||
{
|
||||
public string error_description { get; set; }
|
||||
public string error { get; set; }
|
||||
}
|
||||
|
||||
public class OAuthSuccess
|
||||
{
|
||||
public string access_token { get; set; }
|
||||
public int expires_in { get; set; }
|
||||
}
|
||||
|
||||
public class AuthRequest
|
||||
{
|
||||
public string grant_type { get; set; }
|
||||
public string username { get; set; }
|
||||
public string password { get; set; }
|
||||
}
|
||||
}
|
69
server/FSO.Server.Api.Core/Controllers/Admin/AdminShardsController.cs
Executable file
69
server/FSO.Server.Api.Core/Controllers/Admin/AdminShardsController.cs
Executable file
|
@ -0,0 +1,69 @@
|
|||
using FSO.Server.Api.Core.Utils;
|
||||
using FSO.Server.Common;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Net;
|
||||
|
||||
namespace FSO.Server.Api.Core.Controllers.Admin
|
||||
{
|
||||
[EnableCors("AdminAppPolicy")]
|
||||
[Route("admin/shards")]
|
||||
[ApiController]
|
||||
public class AdminShardsController : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
public IActionResult Get()
|
||||
{
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandAdmin(Request);
|
||||
|
||||
using (var db = api.DAFactory.Get())
|
||||
{
|
||||
var shards = db.Shards.All();
|
||||
return ApiResponse.Json(HttpStatusCode.OK, shards);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("shutdown")]
|
||||
public IActionResult shutdown(ShutdownModel sd)
|
||||
{
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandAdmin(Request);
|
||||
|
||||
ShutdownType type = ShutdownType.SHUTDOWN;
|
||||
if (sd.update) type = ShutdownType.UPDATE;
|
||||
else if (sd.restart) type = ShutdownType.RESTART;
|
||||
|
||||
api.RequestShutdown((uint)sd.timeout, type);
|
||||
|
||||
return ApiResponse.Json(HttpStatusCode.OK, true);
|
||||
}
|
||||
|
||||
[HttpPost("announce")]
|
||||
public IActionResult announce(AnnouncementModel an)
|
||||
{
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandModerator(Request);
|
||||
|
||||
api.BroadcastMessage(an.sender, an.subject, an.message);
|
||||
|
||||
return ApiResponse.Json(HttpStatusCode.OK, true);
|
||||
}
|
||||
}
|
||||
|
||||
public class AnnouncementModel
|
||||
{
|
||||
public string sender;
|
||||
public string subject;
|
||||
public string message;
|
||||
public int[] shard_ids;
|
||||
}
|
||||
|
||||
public class ShutdownModel
|
||||
{
|
||||
public int timeout;
|
||||
public bool restart;
|
||||
public bool update;
|
||||
public int[] shard_ids;
|
||||
}
|
||||
}
|
73
server/FSO.Server.Api.Core/Controllers/Admin/AdminTasksController.cs
Executable file
73
server/FSO.Server.Api.Core/Controllers/Admin/AdminTasksController.cs
Executable file
|
@ -0,0 +1,73 @@
|
|||
using FSO.Server.Api.Core.Utils;
|
||||
using FSO.Server.Database.DA.Tasks;
|
||||
using FSO.Server.Protocol.Gluon.Packets;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
|
||||
namespace FSO.Server.Api.Core.Controllers.Admin
|
||||
{
|
||||
[EnableCors("AdminAppPolicy")]
|
||||
[Route("admin/tasks")]
|
||||
[ApiController]
|
||||
public class AdminTasksController : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
public IActionResult Get(int limit, int offset)
|
||||
{
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandAdmin(Request);
|
||||
|
||||
using (var da = api.DAFactory.Get())
|
||||
{
|
||||
|
||||
if (limit > 100)
|
||||
{
|
||||
limit = 100;
|
||||
}
|
||||
|
||||
var result = da.Tasks.All((int)offset, (int)limit);
|
||||
return ApiResponse.PagedList<DbTask>(Request, HttpStatusCode.OK, result);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("request")]
|
||||
public IActionResult request([FromBody] TaskRequest task)
|
||||
{
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandAdmin(Request);
|
||||
|
||||
var taskServer = api.HostPool.GetByRole(Database.DA.Hosts.DbHostRole.task).FirstOrDefault();
|
||||
if (taskServer == null)
|
||||
{
|
||||
return ApiResponse.Json(HttpStatusCode.OK, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
var id = taskServer.Call(new RequestTask()
|
||||
{
|
||||
TaskType = task.task_type.ToString(),
|
||||
ParameterJson = JsonConvert.SerializeObject(task.parameter),
|
||||
ShardId = (task.shard_id == null || !task.shard_id.HasValue) ? -1 : task.shard_id.Value
|
||||
}).Result;
|
||||
return ApiResponse.Json(HttpStatusCode.OK, id);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ApiResponse.Json(HttpStatusCode.OK, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public class TaskRequest
|
||||
{
|
||||
public DbTaskType task_type;
|
||||
public int? shard_id;
|
||||
public dynamic parameter;
|
||||
}
|
||||
}
|
172
server/FSO.Server.Api.Core/Controllers/Admin/AdminUpdatesController.cs
Executable file
172
server/FSO.Server.Api.Core/Controllers/Admin/AdminUpdatesController.cs
Executable file
|
@ -0,0 +1,172 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using FSO.Server.Api.Core.Models;
|
||||
using FSO.Server.Api.Core.Services;
|
||||
using FSO.Server.Api.Core.Utils;
|
||||
using FSO.Server.Database.DA.Updates;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
|
||||
|
||||
namespace FSO.Server.Api.Core.Controllers.Admin
|
||||
{
|
||||
[EnableCors("AdminAppPolicy")]
|
||||
[Route("admin/updates")]
|
||||
public class AdminUpdatesController : ControllerBase
|
||||
{
|
||||
//List updates
|
||||
[HttpGet]
|
||||
public IActionResult Get(int limit, int offset, string order)
|
||||
{
|
||||
if (limit == 0) limit = 20;
|
||||
if (order == null) order = "date";
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandModerator(Request);
|
||||
using (var da = api.DAFactory.Get())
|
||||
{
|
||||
|
||||
if (limit > 100)
|
||||
{
|
||||
limit = 100;
|
||||
}
|
||||
|
||||
var result = da.Updates.All((int)offset, (int)limit);
|
||||
return ApiResponse.PagedList<DbUpdate>(Request, HttpStatusCode.OK, result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// GET all branches
|
||||
[HttpGet("branches")]
|
||||
public IActionResult GetBranches()
|
||||
{
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandAdmin(Request);
|
||||
using (var da = api.DAFactory.Get())
|
||||
{
|
||||
return new JsonResult(da.Updates.GetBranches().ToList());
|
||||
}
|
||||
}
|
||||
|
||||
// GET all addons
|
||||
[HttpGet("addons")]
|
||||
public IActionResult GetAddons()
|
||||
{
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandAdmin(Request);
|
||||
using (var da = api.DAFactory.Get())
|
||||
{
|
||||
return new JsonResult(da.Updates.GetAddons(20).ToList());
|
||||
}
|
||||
}
|
||||
|
||||
// POST create a branch.
|
||||
[HttpPost("branches")]
|
||||
public IActionResult AddBranch(DbUpdateBranch branch)
|
||||
{
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandAdmin(Request);
|
||||
using (var da = api.DAFactory.Get())
|
||||
{
|
||||
if (da.Updates.AddBranch(branch)) return Ok();
|
||||
else return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
// POST update a branch.
|
||||
[HttpPost("branches/{id}")]
|
||||
public IActionResult UpdateBranch(DbUpdateBranch branch)
|
||||
{
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandAdmin(Request);
|
||||
using (var da = api.DAFactory.Get())
|
||||
{
|
||||
if (da.Updates.UpdateBranchInfo(branch)) return Ok();
|
||||
else return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
public class AddonUploadModel
|
||||
{
|
||||
public string name { get; set; }
|
||||
public string description { get; set; }
|
||||
public IFormFile clientAddon { get; set; }
|
||||
public IFormFile serverAddon { get; set; }
|
||||
}
|
||||
|
||||
static int AddonRequestID = 0;
|
||||
[HttpPost("uploadaddon")]
|
||||
[DisableRequestSizeLimit]
|
||||
[RequestFormLimits(MultipartBodyLengthLimit = 500000000)]
|
||||
public async Task<IActionResult> UploadAddon(AddonUploadModel upload)
|
||||
{
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandAdmin(Request);
|
||||
var reqID = ++AddonRequestID;
|
||||
|
||||
var info = new DbUpdateAddon();
|
||||
if (upload.name == null || upload.name.Length > 128) return BadRequest("Invalid name.");
|
||||
if (upload.description == null || upload.description.Length > 1024) return BadRequest("Invalid description.");
|
||||
info.name = upload.name;
|
||||
info.description = upload.description;
|
||||
info.date = DateTime.UtcNow;
|
||||
|
||||
if (upload.clientAddon == null && upload.serverAddon == null)
|
||||
return BadRequest("client or server addon binary must be uploaded.");
|
||||
|
||||
var addonID = DateTime.UtcNow.Ticks;
|
||||
Directory.CreateDirectory("updateTemp/addons/");
|
||||
if (upload.clientAddon != null)
|
||||
{
|
||||
using (var file = System.IO.File.Open($"updateTemp/addons/client{reqID}.zip", FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
await upload.clientAddon.CopyToAsync(file);
|
||||
}
|
||||
info.addon_zip_url = await api.UpdateUploader.UploadFile($"addons/client{addonID}.zip", $"updateTemp/addons/client{reqID}.zip", $"addon-{addonID}");
|
||||
System.IO.File.Delete($"updateTemp/addons/client{reqID}.zip");
|
||||
}
|
||||
|
||||
if (upload.serverAddon != null)
|
||||
{
|
||||
using (var file = System.IO.File.Open($"updateTemp/addons/server{reqID}.zip", FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
await upload.serverAddon.CopyToAsync(file);
|
||||
}
|
||||
info.server_zip_url = await api.UpdateUploader.UploadFile($"addons/server{addonID}.zip", $"updateTemp/addons/server{reqID}.zip", $"addon-{addonID}");
|
||||
System.IO.File.Delete($"updateTemp/addons/server{reqID}.zip");
|
||||
}
|
||||
|
||||
using (var da = api.DAFactory.Get())
|
||||
{
|
||||
da.Updates.AddAddon(info);
|
||||
return new JsonResult(info);
|
||||
}
|
||||
}
|
||||
|
||||
// GET status for ongoing update generation
|
||||
[HttpGet("updateTask/{id}")]
|
||||
public IActionResult GetTask(int id)
|
||||
{
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandAdmin(Request);
|
||||
var task = GenerateUpdateService.INSTANCE.GetTask(id);
|
||||
if (task == null) return NotFound();
|
||||
else return new JsonResult(task);
|
||||
}
|
||||
|
||||
// POST admin/updates (start update generation)
|
||||
[HttpPost]
|
||||
public IActionResult Post([FromBody]UpdateCreateModel request)
|
||||
{
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandAdmin(Request);
|
||||
var task = GenerateUpdateService.INSTANCE.CreateTask(request);
|
||||
return new JsonResult(task);
|
||||
}
|
||||
}
|
||||
}
|
334
server/FSO.Server.Api.Core/Controllers/Admin/AdminUsersController.cs
Executable file
334
server/FSO.Server.Api.Core/Controllers/Admin/AdminUsersController.cs
Executable file
|
@ -0,0 +1,334 @@
|
|||
using FSO.Server.Api.Core.Utils;
|
||||
using FSO.Server.Common;
|
||||
using FSO.Server.Database.DA.Inbox;
|
||||
using FSO.Server.Database.DA.Users;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System;
|
||||
using System.Net;
|
||||
|
||||
namespace FSO.Server.Api.Core.Controllers.Admin
|
||||
{
|
||||
[EnableCors("AdminAppPolicy")]
|
||||
[Route("admin/users")]
|
||||
[ApiController]
|
||||
public class AdminUsersController : ControllerBase
|
||||
{
|
||||
//Get information about me, useful for the admin user interface to disable UI based on who you login as
|
||||
public IActionResult current()
|
||||
{
|
||||
var api = Api.INSTANCE;
|
||||
|
||||
var user = api.RequireAuthentication(Request);
|
||||
|
||||
using (var da = api.DAFactory.Get())
|
||||
{
|
||||
var userModel = da.Users.GetById(user.UserID);
|
||||
if (userModel == null)
|
||||
{
|
||||
throw new Exception("Unable to find user");
|
||||
}
|
||||
return ApiResponse.Json(HttpStatusCode.OK, userModel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Get the attributes of a specific user
|
||||
[HttpGet("{id}")]
|
||||
public IActionResult Get(string id)
|
||||
{
|
||||
if (id == "current") return current();
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandModerator(Request);
|
||||
using (var da = api.DAFactory.Get())
|
||||
{
|
||||
var userModel = da.Users.GetById(uint.Parse(id));
|
||||
if (userModel == null) { throw new Exception("Unable to find user"); }
|
||||
return ApiResponse.Json(HttpStatusCode.OK, userModel);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unbans a user by IP and user.
|
||||
/// </summary>
|
||||
/// <param name="user_id">ID of user to unban.</param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Route("admin/unban")]
|
||||
public IActionResult UnbanUser([FromBody] string user_id)
|
||||
{
|
||||
Api api = Api.INSTANCE;
|
||||
|
||||
api.DemandModerator(Request);
|
||||
|
||||
using (var da = api.DAFactory.Get())
|
||||
{
|
||||
User userModel = da.Users.GetById(uint.Parse(user_id));
|
||||
|
||||
if(userModel.is_banned)
|
||||
{
|
||||
da.Users.UpdateBanned(uint.Parse(user_id), false);
|
||||
}
|
||||
|
||||
var ban = da.Bans.GetByIP(userModel.last_ip);
|
||||
|
||||
if (ban!=null)
|
||||
{
|
||||
da.Bans.Remove(userModel.user_id);
|
||||
}
|
||||
|
||||
return ApiResponse.Json(HttpStatusCode.OK, new
|
||||
{
|
||||
status = "success"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends an in-game email message to a player.
|
||||
/// </summary>
|
||||
/// <param name="mail"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Route("admin/mail")]
|
||||
public IActionResult SendMail(MailCreateModel mail)
|
||||
{
|
||||
Api api = Api.INSTANCE;
|
||||
|
||||
api.DemandAdmin(Request);
|
||||
|
||||
using (var da = api.DAFactory.Get())
|
||||
{
|
||||
User recipient = da.Users.GetById(uint.Parse(mail.target_id));
|
||||
|
||||
if (recipient == null)
|
||||
{
|
||||
return ApiResponse.Json(HttpStatusCode.OK, new
|
||||
{
|
||||
status = "invalid_target_id"
|
||||
});
|
||||
}
|
||||
|
||||
if (mail.subject.Trim() == "")
|
||||
{
|
||||
return ApiResponse.Json(HttpStatusCode.OK, new
|
||||
{
|
||||
status = "subject_empty"
|
||||
});
|
||||
}
|
||||
|
||||
if (mail.body.Trim() == "")
|
||||
{
|
||||
return ApiResponse.Json(HttpStatusCode.OK, new
|
||||
{
|
||||
status = "body_empty"
|
||||
});
|
||||
}
|
||||
|
||||
// Save mail in db
|
||||
int message_id = da.Inbox.CreateMessage(new DbInboxMsg
|
||||
{
|
||||
sender_id = 2147483648,
|
||||
target_id = uint.Parse(mail.target_id),
|
||||
subject = mail.subject,
|
||||
body = mail.body,
|
||||
sender_name = "FreeSO Staff",
|
||||
time = DateTime.UtcNow,
|
||||
msg_type = 4,
|
||||
msg_subtype = 0,
|
||||
read_state = 0,
|
||||
});
|
||||
|
||||
// Try and notify the user ingame
|
||||
api.RequestMailNotify(message_id, mail.subject, mail.body, uint.Parse(mail.target_id));
|
||||
|
||||
return ApiResponse.Json(HttpStatusCode.OK, new
|
||||
{
|
||||
status = "success"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Kicks a user out the current session.
|
||||
/// </summary>
|
||||
/// <param name="kick"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Route("admin/kick")]
|
||||
public IActionResult KickUser([FromBody] string user_id)
|
||||
{
|
||||
Api api = Api.INSTANCE;
|
||||
|
||||
api.DemandModerator(Request);
|
||||
|
||||
api.RequestUserDisconnect(uint.Parse(user_id));
|
||||
|
||||
return ApiResponse.Json(HttpStatusCode.OK, new {
|
||||
status = "success"
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bans a user and kicks them.
|
||||
/// </summary>
|
||||
/// <param name="ban"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Route("admin/ban")]
|
||||
public IActionResult BanUser(BanCreateModel ban)
|
||||
{
|
||||
Api api = Api.INSTANCE;
|
||||
|
||||
api.DemandModerator(Request);
|
||||
|
||||
using (var da = api.DAFactory.Get())
|
||||
{
|
||||
User userModel = da.Users.GetById(uint.Parse(ban.user_id));
|
||||
|
||||
if (userModel == null)
|
||||
{
|
||||
return ApiResponse.Json(HttpStatusCode.OK, new
|
||||
{
|
||||
status = "invalid_id"
|
||||
});
|
||||
}
|
||||
|
||||
if (ban.ban_type == "ip")
|
||||
{
|
||||
if (da.Bans.GetByIP(userModel.last_ip) != null)
|
||||
{
|
||||
return ApiResponse.Json(HttpStatusCode.OK, new
|
||||
{
|
||||
status = "already_banned"
|
||||
});
|
||||
}
|
||||
|
||||
if (userModel.last_ip == "127.0.0.1")
|
||||
{
|
||||
return ApiResponse.Json(HttpStatusCode.OK, new
|
||||
{
|
||||
status = "invalid_ip"
|
||||
});
|
||||
}
|
||||
|
||||
da.Bans.Add(userModel.last_ip, userModel.user_id, ban.reason, int.Parse(ban.end_date), userModel.client_id);
|
||||
|
||||
api.RequestUserDisconnect(userModel.user_id);
|
||||
|
||||
api.SendBanMail(userModel.username, userModel.email, uint.Parse(ban.end_date));
|
||||
|
||||
return ApiResponse.Json(HttpStatusCode.OK, new
|
||||
{
|
||||
status = "success"
|
||||
});
|
||||
}
|
||||
else if (ban.ban_type == "user")
|
||||
{
|
||||
if (userModel.is_banned)
|
||||
{
|
||||
return ApiResponse.Json(HttpStatusCode.NotFound, new
|
||||
{
|
||||
status = "already_banned"
|
||||
});
|
||||
}
|
||||
|
||||
da.Users.UpdateBanned(userModel.user_id, true);
|
||||
|
||||
api.RequestUserDisconnect(userModel.user_id);
|
||||
|
||||
api.SendBanMail(userModel.username, userModel.email, uint.Parse(ban.end_date));
|
||||
|
||||
return ApiResponse.Json(HttpStatusCode.OK, new
|
||||
{
|
||||
status = "success"
|
||||
});
|
||||
}
|
||||
|
||||
return ApiResponse.Json(HttpStatusCode.OK, new
|
||||
{
|
||||
status = "invalid_ban_type"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//List users
|
||||
[HttpGet]
|
||||
public IActionResult Get(int limit, int offset, string order)
|
||||
{
|
||||
if (limit == 0) limit = 20;
|
||||
if (order == null) order = "register_date";
|
||||
var api = Api.INSTANCE;
|
||||
api.DemandModerator(Request);
|
||||
using (var da = api.DAFactory.Get())
|
||||
{
|
||||
|
||||
if (limit > 100)
|
||||
{
|
||||
limit = 100;
|
||||
}
|
||||
|
||||
var result = da.Users.All((int)offset, (int)limit);
|
||||
return ApiResponse.PagedList<User>(Request, HttpStatusCode.OK, result);
|
||||
}
|
||||
}
|
||||
|
||||
//Create a new user
|
||||
[HttpPost]
|
||||
public IActionResult Post(UserCreateModel user)
|
||||
{
|
||||
var api = Api.INSTANCE;
|
||||
var nuser = api.RequireAuthentication(Request);
|
||||
api.DemandModerator(nuser);
|
||||
|
||||
if (user.is_admin)
|
||||
{
|
||||
//I need admin claim to do this
|
||||
api.DemandAdmin(nuser);
|
||||
}
|
||||
|
||||
using (var da = api.DAFactory.Get())
|
||||
{
|
||||
var userModel = new User();
|
||||
userModel.username = user.username;
|
||||
userModel.email = user.email;
|
||||
userModel.is_admin = user.is_admin;
|
||||
userModel.is_moderator = user.is_moderator;
|
||||
userModel.user_state = UserState.valid;
|
||||
userModel.register_date = Epoch.Now;
|
||||
userModel.is_banned = false;
|
||||
|
||||
var userId = da.Users.Create(userModel);
|
||||
|
||||
userModel = da.Users.GetById(userId);
|
||||
if (userModel == null) { throw new Exception("Unable to find user"); }
|
||||
return ApiResponse.Json(HttpStatusCode.OK, userModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class UserCreateModel
|
||||
{
|
||||
public string username { get; set; }
|
||||
public string email { get; set; }
|
||||
public string password { get; set; }
|
||||
public bool is_admin { get; set; }
|
||||
public bool is_moderator { get; set; }
|
||||
}
|
||||
|
||||
public class BanCreateModel
|
||||
{
|
||||
public string ban_type { get; set; }
|
||||
public string user_id { get; set; }
|
||||
public string reason { get; set; }
|
||||
public string end_date { get; set; }
|
||||
}
|
||||
|
||||
public class MailCreateModel
|
||||
{
|
||||
public string target_id { get; set; }
|
||||
public string subject { get; set; }
|
||||
public string body { get; set; }
|
||||
public string sender_name { get; set; }
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue