mirror of
https://github.com/streetwriters/notesnook-sync-server.git
synced 2026-03-06 05:40:51 +00:00
api: move to atomic password reset
This commit is contained in:
committed by
Abdullah Atta
parent
b9385ae112
commit
9424afed68
@@ -18,7 +18,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Security.Claims;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http.Timeouts;
|
||||
@@ -28,13 +30,16 @@ using Notesnook.API.Interfaces;
|
||||
using Notesnook.API.Models;
|
||||
using Notesnook.API.Models.Responses;
|
||||
using Streetwriters.Common;
|
||||
using Streetwriters.Common.Accessors;
|
||||
using Streetwriters.Common.Extensions;
|
||||
using Streetwriters.Common.Messages;
|
||||
|
||||
namespace Notesnook.API.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
[Route("users")]
|
||||
public class UsersController(IUserService UserService, ILogger<UsersController> logger) : ControllerBase
|
||||
public class UsersController(IUserService UserService, WampServiceAccessor serviceAccessor, ILogger<UsersController> logger) : ControllerBase
|
||||
{
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
@@ -85,6 +90,43 @@ namespace Notesnook.API.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPatch("password/{type}")]
|
||||
public async Task<IActionResult> ChangePassword([FromRoute] string type, [FromBody] ChangePasswordForm form)
|
||||
{
|
||||
var userId = User.GetUserId();
|
||||
var clientId = User.FindFirstValue("client_id");
|
||||
var jti = User.FindFirstValue("jti");
|
||||
var isPasswordReset = type == "reset";
|
||||
try
|
||||
{
|
||||
var result = isPasswordReset ? await serviceAccessor.UserAccountService.ResetPasswordAsync(userId, form.NewPassword) : await serviceAccessor.UserAccountService.ChangePasswordAsync(userId, form.OldPassword, form.NewPassword);
|
||||
if (!result)
|
||||
return BadRequest("Failed to change password.");
|
||||
|
||||
await UserService.SetUserKeysAsync(userId, form.UserKeys);
|
||||
|
||||
await serviceAccessor.UserAccountService.ClearSessionsAsync(userId, clientId, all: false, jti, null);
|
||||
|
||||
await WampServers.MessengerServer.PublishMessageAsync(MessengerServerTopics.SendSSETopic, new SendSSEMessage
|
||||
{
|
||||
UserId = userId,
|
||||
OriginTokenId = User.FindFirstValue("jti"),
|
||||
Message = new Message
|
||||
{
|
||||
Type = "logout",
|
||||
Data = JsonSerializer.Serialize(new { reason = "Password changed." })
|
||||
}
|
||||
});
|
||||
|
||||
return Ok();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "Failed to change password");
|
||||
return BadRequest(new { error = ex.Message });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("reset")]
|
||||
public async Task<IActionResult> Reset([FromForm] bool removeAttachments)
|
||||
{
|
||||
|
||||
24
Notesnook.API/Models/ChangePasswordForm.cs
Normal file
24
Notesnook.API/Models/ChangePasswordForm.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Notesnook.API.Models
|
||||
{
|
||||
public class ChangePasswordForm
|
||||
{
|
||||
public string? OldPassword
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
[Required]
|
||||
public required string NewPassword
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
[Required]
|
||||
public required UserKeys UserKeys
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
}
|
||||
}
|
||||
19
Notesnook.API/Models/ResetPasswordForm.cs
Normal file
19
Notesnook.API/Models/ResetPasswordForm.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Notesnook.API.Models
|
||||
{
|
||||
public class ResetPasswordForm
|
||||
{
|
||||
[Required]
|
||||
public required string NewPassword
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
[Required]
|
||||
public required UserKeys UserKeys
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,11 @@ namespace Notesnook.API.Models.Responses
|
||||
|
||||
[JsonPropertyName("monographPasswordsKey")]
|
||||
public EncryptedData? MonographPasswordsKey { get; set; }
|
||||
[JsonPropertyName("dataEncryptionKey")]
|
||||
public EncryptedData? DataEncryptionKey { get; set; }
|
||||
|
||||
[JsonPropertyName("legacyDataEncryptionKey")]
|
||||
public EncryptedData? LegacyDataEncryptionKey { get; set; }
|
||||
|
||||
[JsonPropertyName("inboxKeys")]
|
||||
public InboxKeys? InboxKeys { get; set; }
|
||||
|
||||
@@ -98,6 +98,14 @@ namespace Notesnook.API.Models
|
||||
get; set;
|
||||
}
|
||||
|
||||
[JsonPropertyName("keyVersion")]
|
||||
[DataMember(Name = "keyVersion")]
|
||||
[MessagePack.Key("keyVersion")]
|
||||
public int? KeyVersion
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
[JsonPropertyName("alg")]
|
||||
[DataMember(Name = "alg")]
|
||||
[MessagePack.Key("alg")]
|
||||
|
||||
@@ -24,6 +24,8 @@ namespace Notesnook.API.Models
|
||||
public EncryptedData? AttachmentsKey { get; set; }
|
||||
public EncryptedData? MonographPasswordsKey { get; set; }
|
||||
public InboxKeys? InboxKeys { get; set; }
|
||||
public EncryptedData? DataEncryptionKey { get; set; }
|
||||
public EncryptedData? LegacyDataEncryptionKey { get; set; }
|
||||
}
|
||||
|
||||
public class InboxKeys
|
||||
|
||||
@@ -55,6 +55,8 @@ namespace Notesnook.API.Models
|
||||
public EncryptedData? VaultKey { get; set; }
|
||||
public EncryptedData? AttachmentsKey { get; set; }
|
||||
public EncryptedData? MonographPasswordsKey { get; set; }
|
||||
public EncryptedData? DataEncryptionKey { get; set; }
|
||||
public EncryptedData? LegacyDataEncryptionKey { get; set; }
|
||||
public InboxKeys? InboxKeys { get; set; }
|
||||
public Limit? StorageLimit { get; set; }
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
@@ -133,6 +134,8 @@ namespace Notesnook.API.Services
|
||||
PhoneNumber = user.PhoneNumber,
|
||||
AttachmentsKey = userSettings.AttachmentsKey,
|
||||
MonographPasswordsKey = userSettings.MonographPasswordsKey,
|
||||
DataEncryptionKey = userSettings.DataEncryptionKey,
|
||||
LegacyDataEncryptionKey = userSettings.LegacyDataEncryptionKey,
|
||||
InboxKeys = userSettings.InboxKeys,
|
||||
Salt = userSettings.Salt,
|
||||
Subscription = subscription,
|
||||
@@ -155,6 +158,11 @@ namespace Notesnook.API.Services
|
||||
{
|
||||
userSettings.MonographPasswordsKey = keys.MonographPasswordsKey;
|
||||
}
|
||||
if (keys.DataEncryptionKey != null)
|
||||
userSettings.DataEncryptionKey = keys.DataEncryptionKey;
|
||||
if (keys.LegacyDataEncryptionKey != null)
|
||||
userSettings.LegacyDataEncryptionKey = keys.LegacyDataEncryptionKey;
|
||||
|
||||
if (keys.InboxKeys != null)
|
||||
{
|
||||
if (keys.InboxKeys.Public == null || keys.InboxKeys.Private == null)
|
||||
@@ -268,6 +276,8 @@ namespace Notesnook.API.Services
|
||||
|
||||
userSettings.AttachmentsKey = null;
|
||||
userSettings.MonographPasswordsKey = null;
|
||||
userSettings.DataEncryptionKey = null;
|
||||
userSettings.LegacyDataEncryptionKey = null;
|
||||
userSettings.VaultKey = null;
|
||||
userSettings.InboxKeys = null;
|
||||
userSettings.LastSynced = 0;
|
||||
|
||||
Reference in New Issue
Block a user