Skip to content

Commit

Permalink
Merge
Browse files Browse the repository at this point in the history
  • Loading branch information
SpikeViper committed Dec 7, 2024
1 parent fa30c35 commit 6233f7e
Show file tree
Hide file tree
Showing 13 changed files with 285 additions and 19 deletions.
106 changes: 106 additions & 0 deletions Valour/Client/Components/Menus/Modals/ChangeUsernameModal.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
@inject ValourClient Client
@inherits Modal<ChangeUsernameModal.Params>

<div class="col-md-12">
<section class="modal-bg">
<h3>Change your username</h3>
<h5>@_changeUsernameMessage</h5>

<div class="form-group mt-2">
<label class="m-2">New Username</label>
<input id="new-username-input" type="text" autocomplete="off" class="form-control" @bind-value="@_newUsername" />
<label class="m-2">Password</label>
<input id="password-input" type="password" autocomplete="current-password" class="form-control" @bind-value="@_password" />
</div>
<br />

<ResultLabel Result="@_result" />

<br />
<div @onclick="@OnCancel" class="btn v-btn d-inline-block">Cancel</div>
@if (_canChangeUsername)
{
<div @onclick="@OnConfirm" class="btn v-btn danger d-inline-block">Confirm</div>
}
</section>
</div>

@code {
public class Params {}
private string _changeUsernameMessage;
private bool _canChangeUsername = false;

private string _newUsername = "";
private string _password = "";

private ITaskResult _result;


private void OnCancel()
{
Close();
}

private async Task OnConfirm()
{
var toastData = new ProgressToastData<TaskResult>()
{
ProgressTask = Client.UpdateMyUsernameAsync(_newUsername, _password),
Title = "Changing Username",
Message = "Updating...",
SuccessMessage = "Username updated!",
};

var result = await ToastContainer.Instance.WaitToastWithTaskResult(toastData);
if (result.Success)
{
Close();
}
else
{
_result = result;
StateHasChanged();
}
}

private void SetChangeUsernameMessage()
{
var user = Client.Me;
double daysSinceLastChange = 0;
if (user.NameChangeTime is not null)
{
daysSinceLastChange = (DateTime.UtcNow - user.NameChangeTime.Value).TotalDays;
}

if (user.Subscription is null)
{
if (daysSinceLastChange < 30)
{
var daysLeft = 30 - daysSinceLastChange;
_changeUsernameMessage = $"You can change your username again in {daysLeft.ToString("F0")} {(daysLeft > 1 ? "days" : "day")}.\nStargazers can change their username every 7 days!";
}
else
{
_canChangeUsername = true;
}
}
else
{
if (daysSinceLastChange < 7)
{
var daysLeft = 7 - daysSinceLastChange;
_changeUsernameMessage = $"You can change your username again in {daysLeft.ToString("F0")} {(daysLeft > 1 ? "days" : "day")}.";
}
else
{
_canChangeUsername = true;
}
}
}

protected override void OnInitialized()
{
base.OnInitialized();
SetChangeUsernameMessage();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.modal-bg {
background-color: var(--main-2);
border-radius: 2em;
text-align: center;
padding: 30px;
max-width: 400px
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
<div class="btn-row">
<button class="btn v-btn danger" @onclick="@OnClickDeleteAccount">Delete my Account</button>
<button class="btn v-btn secondary" @onclick="@OnClickChangePassword">Change Password</button>
<button class="btn v-btn secondary" onclick="@OnClickChangeUsername">Change Username</button>
</div>
<br/>
<br/>
Expand All @@ -71,12 +72,12 @@

[CascadingParameter]
public ModalRoot ModalRoot { get; set; }

[Parameter]
public User User { get; set; }

private UserInfoComponent _infoPreview;

private string _tag;
private ITaskResult _tagChangeResult;

Expand All @@ -88,11 +89,12 @@

private int _statusCode;
private ITaskResult _statusCodeChangeResult;

private async Task OnStatusApply()
{
var oldStatus = User.Status;
User.Status = _status;

_statusChangeResult = await User.UpdateAsync();

// Rollback change if it failed
Expand All @@ -104,7 +106,7 @@
StateHasChanged();
_infoPreview.UpdateAll();
}

private async Task OnTagApply()
{
if (_tag.Length != 4)
Expand All @@ -123,17 +125,18 @@
return;
}
}

var oldTag = User.Tag;
User.Tag = _tag;

_tagChangeResult = await User.UpdateAsync();

// Rollback change if it failed
if (!_tagChangeResult.Success)
{
User.Tag = oldTag;
}

StateHasChanged();
_infoPreview.UpdateAll();
}
Expand All @@ -142,8 +145,9 @@
{
var oldStatusCode = User.UserStateCode;
User.UserStateCode = _statusCode;

_statusCodeChangeResult = await User.UpdateAsync();

// Rollback change if it failed
if (!_statusCodeChangeResult.Success)
{
Expand Down Expand Up @@ -171,29 +175,30 @@
private async Task LoadFiles(InputFileChangeEventArgs e)
{
var file = e.File;

// 10mb limit
if (file.Size > 10240000)
{
_pfpChangeResult = new TaskResult(false, "Max profile image size is 10mb.");
StateHasChanged();
return;
}

var streamContent = new StreamContent(file.OpenReadStream(10240000));
var content = new MultipartFormDataContent();
streamContent.Headers.ContentType = new MediaTypeHeaderValue(file.ContentType);
content.Add(streamContent, file.Name, file.Name);

var result = await Client.PrimaryNode.PostAsyncWithResponse<string>($"upload/profile", content);

_pfpChangeResult = result;

if (_pfpChangeResult.Success)
{
// We slightly modify the url to force a refresh
_pfpUrl = User.GetAvatar(AvatarFormat.WebpAnimated256) + $"?x={DateTime.Now.Ticks}";
}

StateHasChanged();
_infoPreview.UpdateAll();
}
Expand All @@ -202,9 +207,14 @@
{
ModalRoot.OpenModal<DeleteAccountModal>();
}

private void OnClickChangePassword()
{
ModalRoot.OpenModal<ChangePasswordModal>();
}

private void OnClickChangeUsername()
{
ModalRoot.OpenModal<ChangeUsernameModal>();
}
}
4 changes: 4 additions & 0 deletions Valour/Client/Components/Users/ProfileCard.razor
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
<div class="names">
<p class="nickname">@_name</p>
<p class="name-and-tag" style="@CustomText">@_nameAndTag</p>
@if (User.PriorName is not null)
{
<p class="name-and-tag">Formerly: @User.PriorName</p>
}
<div class="status-bubble">
<div class="arrow"></div>
<p class="status-text">"@(_status)"</p>
Expand Down
14 changes: 13 additions & 1 deletion Valour/Database/User.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,19 @@ public class User : ISharedUser
/// </summary>
[Column("subscription_type")]
public string SubscriptionType { get; set; }


/// <summary>
/// The user's prior username, if they have changed it before.
/// </summary>
[Column("prior_name")]
public string PriorName { get; set; }

/// <summary>
/// The date and time the user last changed their username.
/// </summary>
[Column("name_change_time")]
public DateTime? NameChangeTime { get; set; }

public string GetAvatarUrl(AvatarFormat format = AvatarFormat.Webp256) =>
ISharedUser.GetAvatar(this, format);
}
Expand Down
6 changes: 6 additions & 0 deletions Valour/Sdk/Client/ValourClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,12 @@ public async Task<TaskResult> UpdateMyPasswordAsync(string oldPassword, string n
var model = new ChangePasswordRequest() { OldPassword = oldPassword, NewPassword = newPassword };
return await PrimaryNode.PostAsync("api/users/me/password", model);
}

public async Task<TaskResult> UpdateMyUsernameAsync(string newUsername, string password)
{
var model = new ChangeUsernameRequest() { NewUsername = newUsername, Password = password };
return await PrimaryNode.PostAsync("api/users/me/username", model);
}

// Sad zone
public async Task<TaskResult> DeleteMyAccountAsync(string password)
Expand Down
10 changes: 10 additions & 0 deletions Valour/Sdk/Models/User.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,16 @@ public class User : ClientModel<User, long>, ISharedUser, IMessageAuthor
/// </summary>
public string SubscriptionType { get; set; }

/// <summary>
/// The user's prior username, if they have changed it before.
/// </summary>
public string PriorName { get; set; }

/// <summary>
/// The date and time the user last changed their username.
/// </summary>
public DateTime? NameChangeTime { get; set; }

/// <summary>
/// The subscription the user currently has
/// </summary>
Expand Down
26 changes: 26 additions & 0 deletions Valour/Server/Api/Dynamic/UserApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,32 @@ public static async Task<IResult> ChangePasswordRouteAsync(

return Results.NoContent();
}

[ValourRoute(HttpVerbs.Post, "api/users/me/username")]
[UserRequired(UserPermissionsEnum.FullControl)]
public static async Task<IResult> ChangeUsernameRouteAsync(
[FromBody] ChangeUsernameRequest request,
UserService userService)
{
if (request is null)
{
return ValourResult.BadRequest("Include request in body.");
}

var credential = await userService.GetCredentialAsync(await userService.GetCurrentUserIdAsync());

// Verify password
var validResult = await userService.ValidateCredentialAsync(CredentialType.PASSWORD, credential.Identifier, request.Password);
if (!validResult.Success)
return ValourResult.Forbid(validResult.Message);

var userId = await userService.GetCurrentUserIdAsync();
var result = await userService.ChangeUsernameAsync(userId, request.NewUsername);
if (!result.Success)
return ValourResult.Problem(result.Message);

return Results.NoContent();
}

[ValourRoute(HttpVerbs.Post, "api/users/me/hardDelete")]
[UserRequired(UserPermissionsEnum.FullControl)]
Expand Down
8 changes: 6 additions & 2 deletions Valour/Server/Mapping/UserMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ public static User ToModel(this Valour.Database.User user)
TimeLastActive = user.TimeLastActive,
IsMobile = user.IsMobile,
Compliance = user.Compliance,
SubscriptionType = user.SubscriptionType
SubscriptionType = user.SubscriptionType,
PriorName = user.PriorName,
NameChangeTime = user.NameChangeTime
};
}

Expand All @@ -48,7 +50,9 @@ public static Valour.Database.User ToDatabase(this User user)
TimeLastActive = user.TimeLastActive,
IsMobile = user.IsMobile,
Compliance = user.Compliance,
SubscriptionType = user.SubscriptionType
SubscriptionType = user.SubscriptionType,
PriorName = user.PriorName,
NameChangeTime = user.NameChangeTime
};
}
}
12 changes: 11 additions & 1 deletion Valour/Server/Models/User.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,17 @@ public class User : ServerModel<long>, ISharedUser
/// is subscribed to
/// </summary>
public string SubscriptionType { get; set; }


/// <summary>
/// The user's prior username, if they have changed it before.
/// </summary>
public string PriorName { get; set; }

/// <summary>
/// The date and time the user last changed their username.
/// </summary>
public DateTime? NameChangeTime { get; set; }

/// <summary>
/// The subscription the user currently has
/// </summary>
Expand Down
Loading

0 comments on commit 6233f7e

Please sign in to comment.