mirror of
https://github.com/Damillora/Shioriko.git
synced 2025-02-23 01:13:39 +00:00
feat: separate update profile and password
This commit is contained in:
parent
6581e40f80
commit
c87e76566d
@ -3,6 +3,8 @@ package app
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/Damillora/Shioriko/pkg/database"
|
||||
"github.com/Damillora/Shioriko/pkg/middleware"
|
||||
"github.com/Damillora/Shioriko/pkg/models"
|
||||
"github.com/Damillora/Shioriko/pkg/services"
|
||||
"github.com/gin-gonic/gin"
|
||||
@ -11,6 +13,11 @@ import (
|
||||
|
||||
func InitializeAuthRoutes(g *gin.Engine) {
|
||||
g.POST("/api/auth/login", createToken)
|
||||
|
||||
protected := g.Group("/api/auth").Use(middleware.AuthMiddleware())
|
||||
{
|
||||
protected.POST("/token", createTokenLoggedIn)
|
||||
}
|
||||
}
|
||||
func createToken(c *gin.Context) {
|
||||
var model models.LoginFormModel
|
||||
@ -50,3 +57,21 @@ func createToken(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func createTokenLoggedIn(c *gin.Context) {
|
||||
result, ok := c.Get("user")
|
||||
if ok {
|
||||
user := result.(*database.User)
|
||||
if user != nil {
|
||||
token := services.CreateToken(user)
|
||||
c.JSON(http.StatusOK, models.TokenResponse{
|
||||
Token: token,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
c.JSON(http.StatusUnauthorized, models.ErrorResponse{
|
||||
Code: http.StatusUnauthorized,
|
||||
Message: "No authorized user",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,8 @@ func InitializeUserRoutes(g *gin.Engine) {
|
||||
protected := g.Group("/api/user").Use(middleware.AuthMiddleware())
|
||||
{
|
||||
protected.GET("/profile", userProfile)
|
||||
protected.POST("/update", userUpdate)
|
||||
protected.PUT("/update", userUpdate)
|
||||
protected.PUT("/update-password", userUpdatePassword)
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,7 +115,45 @@ func userUpdate(c *gin.Context) {
|
||||
result, ok := c.Get("user")
|
||||
if ok {
|
||||
user := result.(*database.User)
|
||||
services.UpdateUser(user.ID, model)
|
||||
services.UpdateUserProfile(user.ID, model)
|
||||
c.JSON(http.StatusOK, nil)
|
||||
} else {
|
||||
c.JSON(http.StatusBadRequest, models.ErrorResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: "User does not exist",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func userUpdatePassword(c *gin.Context) {
|
||||
var model models.UserUpdatePasswordModel
|
||||
|
||||
err := c.ShouldBindJSON(&model)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.ErrorResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: err.Error(),
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
validate := validator.New()
|
||||
err = validate.Struct(model)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.ErrorResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: err.Error(),
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
result, ok := c.Get("user")
|
||||
if ok {
|
||||
user := result.(*database.User)
|
||||
services.UpdateUserPassword(user.ID, model)
|
||||
c.JSON(http.StatusOK, nil)
|
||||
} else {
|
||||
c.JSON(http.StatusBadRequest, models.ErrorResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
@ -7,8 +7,11 @@ type UserCreateModel struct {
|
||||
}
|
||||
|
||||
type UserUpdateModel struct {
|
||||
Email string `json:"email" validate:"required,email"`
|
||||
Username string `json:"username" validate:"required"`
|
||||
Email string `json:"email" validate:"required,email"`
|
||||
Username string `json:"username" validate:"required"`
|
||||
}
|
||||
|
||||
type UserUpdatePasswordModel struct {
|
||||
OldPassword string `json:"old_password"`
|
||||
NewPassword string `json:"new_password"`
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ func GetUserFromUsername(username string) *database.User {
|
||||
return &user
|
||||
}
|
||||
|
||||
func UpdateUser(id string, model models.UserUpdateModel) (*database.User, error) {
|
||||
func UpdateUserProfile(id string, model models.UserUpdateModel) (*database.User, error) {
|
||||
var user database.User
|
||||
result := database.DB.Where("id = ?", id).First(&user)
|
||||
|
||||
@ -49,6 +49,19 @@ func UpdateUser(id string, model models.UserUpdateModel) (*database.User, error)
|
||||
user.Email = model.Email
|
||||
user.Username = model.Username
|
||||
|
||||
result = database.DB.Save(&user)
|
||||
if result.Error != nil {
|
||||
return nil, result.Error
|
||||
}
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
|
||||
func UpdateUserPassword(id string, model models.UserUpdatePasswordModel) (*database.User, error) {
|
||||
var user database.User
|
||||
result := database.DB.Where("id = ?", id).First(&user)
|
||||
|
||||
|
||||
if user.Password != "" {
|
||||
verifyErr := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(model.OldPassword))
|
||||
if verifyErr != nil {
|
||||
|
@ -37,6 +37,20 @@ export async function register({ email, username, password }) {
|
||||
return response.data;
|
||||
}
|
||||
|
||||
|
||||
export async function updateToken() {
|
||||
const endpoint = url + "/api/auth/token";
|
||||
const response = await axios({
|
||||
url: endpoint,
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + current_token,
|
||||
},
|
||||
})
|
||||
token.set(response.data.token);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function getTags() {
|
||||
const endpoint = url + "/api/tag";
|
||||
const response = await axios.get(endpoint);
|
||||
@ -200,8 +214,8 @@ export async function updateTag(id, { name, tagTypeId }) {
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function updateUserProfile({ email, username, oldPassword, newPassword }) {
|
||||
const endpoint = url + "/api/tag/" + id;
|
||||
export async function updateUserProfile({ email, username, }) {
|
||||
const endpoint = url + "/api/user/update";
|
||||
const response = await axios({
|
||||
url: endpoint,
|
||||
method: "PUT",
|
||||
@ -210,7 +224,22 @@ export async function updateUserProfile({ email, username, oldPassword, newPassw
|
||||
},
|
||||
withCredentials: true,
|
||||
data: {
|
||||
email, username, oldPassword, newPassword
|
||||
email, username,
|
||||
}
|
||||
})
|
||||
return response.data;
|
||||
}
|
||||
export async function updateUserPassword({ old_password, new_password }) {
|
||||
const endpoint = url + "/api/user/update-password";
|
||||
const response = await axios({
|
||||
url: endpoint,
|
||||
method: "PUT",
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + current_token,
|
||||
},
|
||||
withCredentials: true,
|
||||
data: {
|
||||
old_password, new_password
|
||||
}
|
||||
})
|
||||
return response.data;
|
||||
|
@ -0,0 +1,8 @@
|
||||
<script>
|
||||
</script>
|
||||
|
||||
<div class="panel is-primary">
|
||||
<div class="panel-heading">User Actions</div>
|
||||
<a href="/user/profile" class="panel-block">Profile</a>
|
||||
<a href="/user/password" class="panel-block">Change Password</a>
|
||||
</div>
|
79
web/app/src/routes/user/password/+page.svelte
Normal file
79
web/app/src/routes/user/password/+page.svelte
Normal file
@ -0,0 +1,79 @@
|
||||
<script>
|
||||
import { updateToken, updateUserPassword, } from "$lib/api";
|
||||
import UserActionsPanel from "$lib/components/panels/UserActionsPanel.svelte";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
let loading = $state(false);
|
||||
let updated = $state(false);
|
||||
let form = $state({
|
||||
old_password: "",
|
||||
new_password: "",
|
||||
});
|
||||
|
||||
const getData = async () => {
|
||||
loading = false;
|
||||
};
|
||||
|
||||
const submitForm = async () => {
|
||||
updated = false;
|
||||
await updateUserPassword({ old_password: form.old_password, new_password: form.new_password })
|
||||
await updateToken();
|
||||
updated = true;
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
loading = true;
|
||||
getData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<div class="columns">
|
||||
<div class="column is-one-third">
|
||||
<UserActionsPanel />
|
||||
</div>
|
||||
<div class="column is-two-thirds">
|
||||
<div class="box">
|
||||
<h1 class="title">Change Password</h1>
|
||||
{#if updated}
|
||||
<div class="notification is-success">
|
||||
Password updated!
|
||||
</div>
|
||||
{/if}
|
||||
<form onsubmit={submitForm}>
|
||||
<div class="field">
|
||||
<label class="label" for="old_password">Current Password</label>
|
||||
<div class="control">
|
||||
<input
|
||||
id="old_password"
|
||||
class="input"
|
||||
class:is-skeleton="{loading}"
|
||||
type="password"
|
||||
placeholder="Current password"
|
||||
bind:value={form.old_password}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label" for="new_password">New Password</label>
|
||||
<div class="control">
|
||||
<input
|
||||
id="new_password"
|
||||
class="input"
|
||||
class:is-skeleton="{loading}"
|
||||
type="password"
|
||||
placeholder="New password"
|
||||
bind:value={form.new_password}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<button class="button is-primary is-fullwidth is-outlined" type="submit">Change Password</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
@ -1,26 +1,82 @@
|
||||
<script>
|
||||
import { getUserProfile, updateToken, updateUserProfile } from "$lib/api";
|
||||
import UserActionsPanel from "$lib/components/panels/UserActionsPanel.svelte";
|
||||
import { onMount } from "svelte";
|
||||
import { getUserProfile } from "$lib/api";
|
||||
import AuthRequired from "$lib/components/checks/AuthRequired.svelte";
|
||||
|
||||
let user = $state();
|
||||
let loading = $state(false);
|
||||
let updated = $state(false);
|
||||
let form = $state({
|
||||
email: "",
|
||||
username: "",
|
||||
});
|
||||
|
||||
const getData = async () => {
|
||||
user = await getUserProfile();
|
||||
const user = await getUserProfile();
|
||||
form.email = user.email;
|
||||
form.username = user.username;
|
||||
loading = false;
|
||||
};
|
||||
|
||||
const submitForm = async () => {
|
||||
updated = false;
|
||||
await updateUserProfile({ email: form.email, username: form.username })
|
||||
await updateToken();
|
||||
updated = true;
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
loading = true;
|
||||
getData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<AuthRequired />
|
||||
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
{#if user}
|
||||
<h1 class="title">Welcome, {user.username}</h1>
|
||||
<p>Email: {user.email}</p>
|
||||
<p>Username: {user.username}</p>
|
||||
{/if}
|
||||
<div class="columns">
|
||||
<div class="column is-one-third">
|
||||
<UserActionsPanel />
|
||||
</div>
|
||||
<div class="column is-two-thirds">
|
||||
<div class="box">
|
||||
<h1 class="title">Profile</h1>
|
||||
{#if updated}
|
||||
<div class="notification is-success">
|
||||
Profile updated!
|
||||
</div>
|
||||
{/if}
|
||||
<form onsubmit={submitForm}>
|
||||
<div class="field">
|
||||
<label class="label" for="email">Email</label>
|
||||
<div class="control">
|
||||
<input
|
||||
id="email"
|
||||
class="input"
|
||||
class:is-skeleton="{loading}"
|
||||
type="text"
|
||||
placeholder="Email"
|
||||
bind:value={form.email}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label" for="username">Username</label>
|
||||
<div class="control">
|
||||
<input
|
||||
id="username"
|
||||
class="input"
|
||||
class:is-skeleton="{loading}"
|
||||
type="text"
|
||||
placeholder="Username"
|
||||
bind:value={form.username}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<button class="button is-primary is-fullwidth is-outlined" type="submit">Update</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
Loading…
x
Reference in New Issue
Block a user