UserController.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. <?php
  2. namespace App\Http\Controllers\Api;
  3. use App\Classes\Pterodactyl;
  4. use App\Events\UserUpdateCreditsEvent;
  5. use App\Http\Controllers\Controller;
  6. use App\Models\Configuration;
  7. use App\Models\DiscordUser;
  8. use App\Models\User;
  9. use Illuminate\Contracts\Foundation\Application;
  10. use Illuminate\Contracts\Pagination\LengthAwarePaginator;
  11. use Illuminate\Contracts\Routing\ResponseFactory;
  12. use Illuminate\Database\Eloquent\Builder;
  13. use Illuminate\Database\Eloquent\Collection;
  14. use Illuminate\Database\Eloquent\Model;
  15. use Illuminate\Http\Request;
  16. use Illuminate\Http\Response;
  17. use Illuminate\Support\Facades\App;
  18. use Illuminate\Support\Facades\Hash;
  19. use Illuminate\Support\Str;
  20. use Illuminate\Validation\Rule;
  21. use Illuminate\Validation\ValidationException;
  22. use Spatie\QueryBuilder\QueryBuilder;
  23. class UserController extends Controller
  24. {
  25. const ALLOWED_INCLUDES = ['servers', 'notifications', 'payments', 'vouchers', 'discordUser'];
  26. const ALLOWED_FILTERS = ['name', 'server_limit', 'email', 'pterodactyl_id', 'role', 'suspended'];
  27. /**
  28. * Display a listing of the resource.
  29. *
  30. * @param Request $request
  31. * @return LengthAwarePaginator
  32. */
  33. public function index(Request $request)
  34. {
  35. $query = QueryBuilder::for(User::class)
  36. ->allowedIncludes(self::ALLOWED_INCLUDES)
  37. ->allowedFilters(self::ALLOWED_FILTERS);
  38. return $query->paginate($request->input('per_page') ?? 50);
  39. }
  40. /**
  41. * Display the specified resource.
  42. *
  43. * @param int $id
  44. *
  45. * @return User|Builder|Collection|Model
  46. */
  47. public function show(int $id)
  48. {
  49. $discordUser = DiscordUser::find($id);
  50. $user = $discordUser ? $discordUser->user : User::findOrFail($id);
  51. $query = QueryBuilder::for($user)
  52. ->with('discordUser')
  53. ->allowedIncludes(self::ALLOWED_INCLUDES)
  54. ->where('users.id', '=', $id)
  55. ->orWhereHas('discordUser', function (Builder $builder) use ($id) {
  56. $builder->where('id', '=', $id);
  57. });
  58. return $query->firstOrFail();
  59. }
  60. /**
  61. * Update the specified resource in storage.
  62. *
  63. * @param Request $request
  64. * @param int $id
  65. * @return User
  66. */
  67. public function update(Request $request, int $id)
  68. {
  69. $discordUser = DiscordUser::find($id);
  70. $user = $discordUser ? $discordUser->user : User::findOrFail($id);
  71. $request->validate([
  72. "name" => "sometimes|string|min:4|max:30",
  73. "email" => "sometimes|string|email",
  74. "credits" => "sometimes|numeric|min:0|max:1000000",
  75. "server_limit" => "sometimes|numeric|min:0|max:1000000",
  76. "role" => ['sometimes', Rule::in(['admin', 'mod', 'client', 'member'])],
  77. ]);
  78. $user->update($request->all());
  79. event(new UserUpdateCreditsEvent($user));
  80. return $user;
  81. }
  82. /**
  83. * increments the users credits or/and server_limit
  84. *
  85. * @param Request $request
  86. * @param int $id
  87. * @return User
  88. * @throws ValidationException
  89. */
  90. public function increment(Request $request, int $id)
  91. {
  92. $discordUser = DiscordUser::find($id);
  93. $user = $discordUser ? $discordUser->user : User::findOrFail($id);
  94. $request->validate([
  95. "credits" => "sometimes|numeric|min:0|max:1000000",
  96. "server_limit" => "sometimes|numeric|min:0|max:1000000",
  97. ]);
  98. if ($request->credits) {
  99. if ($user->credits + $request->credits >= 99999999) throw ValidationException::withMessages([
  100. 'credits' => "You can't add this amount of credits because you would exceed the credit limit"
  101. ]);
  102. event(new UserUpdateCreditsEvent($user));
  103. $user->increment('credits', $request->credits);
  104. }
  105. if ($request->server_limit) {
  106. if ($user->server_limit + $request->server_limit >= 2147483647) throw ValidationException::withMessages([
  107. 'server_limit' => "You cannot add this amount of servers because it would exceed the server limit."
  108. ]);
  109. $user->increment('server_limit', $request->server_limit);
  110. }
  111. return $user;
  112. }
  113. /**
  114. * decrements the users credits or/and server_limit
  115. *
  116. * @param Request $request
  117. * @param int $id
  118. * @return User
  119. * @throws ValidationException
  120. */
  121. public function decrement(Request $request, int $id)
  122. {
  123. $discordUser = DiscordUser::find($id);
  124. $user = $discordUser ? $discordUser->user : User::findOrFail($id);
  125. $request->validate([
  126. "credits" => "sometimes|numeric|min:0|max:1000000",
  127. "server_limit" => "sometimes|numeric|min:0|max:1000000",
  128. ]);
  129. if ($request->credits) {
  130. if ($user->credits - $request->credits < 0) throw ValidationException::withMessages([
  131. 'credits' => "You can't remove this amount of credits because you would exceed the minimum credit limit"
  132. ]);
  133. $user->decrement('credits', $request->credits);
  134. }
  135. if ($request->server_limit) {
  136. if ($user->server_limit - $request->server_limit < 0) throw ValidationException::withMessages([
  137. 'server_limit' => "You cannot remove this amount of servers because it would exceed the minimum server."
  138. ]);
  139. $user->decrement('server_limit', $request->server_limit);
  140. }
  141. return $user;
  142. }
  143. /**
  144. * @throws ValidationException
  145. */
  146. public function store(Request $request)
  147. {
  148. $request->validate([
  149. 'name' => ['required', 'string', 'max:30', 'min:4', 'alpha_num', 'unique:users'],
  150. 'email' => ['required', 'string', 'email', 'max:64', 'unique:users'],
  151. 'password' => ['required', 'string', 'min:8', 'max:191'],
  152. ]);
  153. $user = User::create([
  154. 'name' => $request->input('name'),
  155. 'email' => $request->input('email'),
  156. 'credits' => Configuration::getValueByKey('INITIAL_CREDITS', 150),
  157. 'server_limit' => Configuration::getValueByKey('INITIAL_SERVER_LIMIT', 1),
  158. 'password' => Hash::make($request->input('password')),
  159. ]);
  160. $response = Pterodactyl::client()->post('/application/users', [
  161. "external_id" => App::environment('local') ? Str::random(16) : (string)$user->id,
  162. "username" => $user->name,
  163. "email" => $user->email,
  164. "first_name" => $user->name,
  165. "last_name" => $user->name,
  166. "password" => $request->input('password'),
  167. "root_admin" => false,
  168. "language" => "en"
  169. ]);
  170. if ($response->failed()) {
  171. $user->delete();
  172. throw ValidationException::withMessages([
  173. 'pterodactyl_error_message' => $response->toException()->getMessage(),
  174. 'pterodactyl_error_status' => $response->toException()->getCode()
  175. ]);
  176. }
  177. $user->update([
  178. 'pterodactyl_id' => $response->json()['attributes']['id']
  179. ]);
  180. return $user;
  181. }
  182. /**
  183. * Remove the specified resource from storage.
  184. *
  185. * @param int $id
  186. * @return Application|Response|ResponseFactory
  187. */
  188. public function destroy(int $id)
  189. {
  190. $discordUser = DiscordUser::find($id);
  191. $user = $discordUser ? $discordUser->user : User::findOrFail($id);
  192. $user->delete();
  193. return response($user, 200);
  194. }
  195. }