// ========================================================================== // UsersController.cs // Squidex Headless CMS // ========================================================================== // Copyright (c) Squidex Group // All rights reserved. // ========================================================================== using System.IO; using System.Linq; using System.Net.Http; using System.Reflection; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using NSwag.Annotations; using Squidex.Controllers.Api.Users.Models; using Squidex.Infrastructure.Reflection; using Squidex.Pipeline; using Squidex.Read.Users; // ReSharper disable InvertIf namespace Squidex.Controllers.Api.Users { /// /// Readonly API to retrieve information about squidex users. /// [ApiExceptionFilter] [SwaggerTag("Users")] public class UsersController : Controller { private static readonly byte[] AvatarBytes; private readonly UserManager userManager; private readonly IUserPictureStore userPictureStore; static UsersController() { var assembly = typeof(UsersController).GetTypeInfo().Assembly; using (var avatarStream = assembly.GetManifestResourceStream("Squidex.Controllers.Api.Users.Assets.Avatar.png")) { AvatarBytes = new byte[avatarStream.Length]; avatarStream.Read(AvatarBytes, 0, AvatarBytes.Length); } } public UsersController(UserManager userManager, IUserPictureStore userPictureStore) { this.userManager = userManager; this.userPictureStore = userPictureStore; } /// /// Get users by query. /// /// The query to search the user by email address. Case invariant. /// /// Search the user by query that contains the email address or the part of the email address. /// /// /// 200 => Users returned. /// [Authorize] [HttpGet] [Route("users")] [ProducesResponseType(typeof(UserDto[]), 200)] public async Task GetUsers(string query) { var entities = await userManager.QueryByEmailAsync(query ?? string.Empty); var models = entities.Select(x => SimpleMapper.Map(x, new UserDto { DisplayName = x.DisplayName(), PictureUrl = x.PictureUrl() })).ToArray(); return Ok(models); } /// /// Get user by id. /// /// The id of the user (GUID). /// /// 200 => User found. /// 404 => User not found. /// [Authorize] [HttpGet] [Route("users/{id}/")] [ProducesResponseType(typeof(UserDto), 200)] public async Task GetUser(string id) { var entity = await userManager.FindByIdAsync(id); if (entity == null) { return NotFound(); } var response = SimpleMapper.Map(entity, new UserDto { DisplayName = entity.DisplayName(), PictureUrl = entity.PictureUrl() }); return Ok(response); } /// /// Get user picture by id. /// /// The id of the user (GUID). /// /// 200 => User found and image or fallback returned. /// 404 => User not found. /// [HttpGet] [Route("users/{id}/picture")] [ProducesResponseType(200)] public async Task GetUserPicture(string id) { var entity = await userManager.FindByIdAsync(id); if (entity == null) { return NotFound(); } try { if (entity.IsPictureUrlStored()) { return new FileStreamResult(await userPictureStore.DownloadAsync(entity.Id), "image/png"); } } catch { return new FileStreamResult(new MemoryStream(AvatarBytes), "image/png"); } using (var client = new HttpClient()) { var url = entity.PictureNormalizedUrl(); if (!string.IsNullOrWhiteSpace(url)) { var response = await client.GetAsync(url); if (response.IsSuccessStatusCode) { return new FileStreamResult(await response.Content.ReadAsStreamAsync(), response.Content.Headers.ContentType.ToString()); } } } return new FileStreamResult(new MemoryStream(AvatarBytes), "image/png"); } } }