🐛 Bug fixes of risk detection

💄 Optimized UI
This commit is contained in:
LittleSheep 2024-05-01 01:33:11 +08:00
parent 6ec48aaa8a
commit 29a33331e4
5 changed files with 57 additions and 14 deletions

11
.idea/workspace.xml generated
View File

@ -4,10 +4,12 @@
<option name="autoReloadType" value="ALL" /> <option name="autoReloadType" value="ALL" />
</component> </component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="3fefb2c4-b6f9-466b-a523-53352e8d6f95" name="更改" comment=":sparkles: Bug fixes"> <list default="true" id="3fefb2c4-b6f9-466b-a523-53352e8d6f95" name="更改" comment=":sparkles: Batch mark notify as read API">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/pkg/server/notifications_api.go" beforeDir="false" afterPath="$PROJECT_DIR$/pkg/server/notifications_api.go" afterDir="false" /> <change beforePath="$PROJECT_DIR$/pkg/server/auth_api.go" beforeDir="false" afterPath="$PROJECT_DIR$/pkg/server/auth_api.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/pkg/server/startup.go" beforeDir="false" afterPath="$PROJECT_DIR$/pkg/server/startup.go" afterDir="false" /> <change beforePath="$PROJECT_DIR$/pkg/services/ticket.go" beforeDir="false" afterPath="$PROJECT_DIR$/pkg/services/ticket.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/pkg/views/partials/header.gohtml" beforeDir="false" afterPath="$PROJECT_DIR$/pkg/views/partials/header.gohtml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/pkg/views/users/personalize.gohtml" beforeDir="false" afterPath="$PROJECT_DIR$/pkg/views/users/personalize.gohtml" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -140,7 +142,8 @@
<MESSAGE value=":lipstick: Fix ui design" /> <MESSAGE value=":lipstick: Fix ui design" />
<MESSAGE value=":bug: Bug fixes of design" /> <MESSAGE value=":bug: Bug fixes of design" />
<MESSAGE value=":sparkles: Bug fixes" /> <MESSAGE value=":sparkles: Bug fixes" />
<option name="LAST_COMMIT_MESSAGE" value=":sparkles: Bug fixes" /> <MESSAGE value=":sparkles: Batch mark notify as read API" />
<option name="LAST_COMMIT_MESSAGE" value=":sparkles: Batch mark notify as read API" />
</component> </component>
<component name="VgoProject"> <component name="VgoProject">
<settings-migrated>true</settings-migrated> <settings-migrated>true</settings-migrated>

View File

@ -118,7 +118,7 @@ func getToken(c *fiber.Ctx) error {
if err != nil { if err != nil {
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("invalid password: %v", err.Error())) return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("invalid password: %v", err.Error()))
} else if err := ticket.IsAvailable(); err != nil { } else if err := ticket.IsAvailable(); err != nil {
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("risk detected: %v", err)) return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("risk detected: %v (ticketId=%d)", err, ticket.ID))
} }
access, refresh, err = services.ExchangeOauthToken(data.ClientID, data.ClientSecret, data.RedirectUri, *ticket.GrantToken) access, refresh, err = services.ExchangeOauthToken(data.ClientID, data.ClientSecret, data.RedirectUri, *ticket.GrantToken)
if err != nil { if err != nil {

View File

@ -12,11 +12,21 @@ import (
) )
func DetectRisk(user models.Account, ip, ua string) bool { func DetectRisk(user models.Account, ip, ua string) bool {
var availableFactor int64
if err := database.C.
Where(models.AuthFactor{AccountID: user.ID}).
Where("type != ?", models.PasswordAuthFactor).
Model(models.AuthFactor{}).
Where(&availableFactor); err != nil || availableFactor <= 0 {
return false
}
var secureFactor int64 var secureFactor int64
if err := database.C.Where(models.AuthTicket{ if err := database.C.
AccountID: user.ID, Where(models.AuthTicket{AccountID: user.ID, IpAddress: ip}).
IpAddress: ip, Where("available_at IS NOT NULL").
}).Model(models.AuthTicket{}).Count(&secureFactor).Error; err == nil { Model(models.AuthTicket{}).
Count(&secureFactor).Error; err == nil {
if secureFactor >= 1 { if secureFactor >= 1 {
return false return false
} }

View File

@ -83,6 +83,7 @@
html, body { html, body {
padding: 0; padding: 0;
margin: 0; margin: 0;
background-color: var(--md-sys-color-surface-container);
} }
</style> </style>
</head> </head>

View File

@ -8,9 +8,13 @@
<div class="right-part"> <div class="right-part">
<div class="responsive-title-gap"></div> <div class="responsive-title-gap"></div>
<div class="action-form"> <div class="personalize-actions">
<div class="input-label">Avatar</div> <md-filled-tonal-button class="personalize-action" data-target="avatar">
Edit Avatar
<span slot="icon" class="material-symbols-outlined">account_circle</span>
</md-filled-tonal-button>
<input <input
hidden
id="avatar-input" id="avatar-input"
class="block-field" class="block-field"
name="avatar" name="avatar"
@ -19,8 +23,12 @@
placeholder="Avatar" placeholder="Avatar"
> >
<div class="input-label">Banner</div> <md-filled-tonal-button class="personalize-action" data-target="banner">
Edit Banner
<span slot="icon" class="material-symbols-outlined">background_replace</span>
</md-filled-tonal-button>
<input <input
hidden
id="banner-input" id="banner-input"
class="block-field" class="block-field"
name="banner" name="banner"
@ -30,8 +38,6 @@
> >
</div> </div>
<md-divider style="margin: 1rem 0"></md-divider>
<form class="action-form" action="/users/me/personalize" method="POST"> <form class="action-form" action="/users/me/personalize" method="POST">
<div class="columns-two"> <div class="columns-two">
<md-outlined-text-field <md-outlined-text-field
@ -110,9 +116,32 @@
font-size: 14px; font-size: 14px;
text-align: left; text-align: left;
} }
.personalize-actions {
display: flex;
gap: 0.5rem;
margin-bottom: 1.5rem;
margin-left: -0.2rem;
margin-right: -0.2rem;
}
.personalize-actions .personalize-action {
width: fit-content;
}
.personalize-action .material-symbols-outlined {
font-size: 20px;
margin-bottom: 2px;
}
</style> </style>
<script> <script>
document.querySelectorAll(".personalize-action").forEach((element) => {
element.addEventListener("click", (_) => {
document.getElementById(`${element.getAttribute("data-target")}-input`).click();
})
})
document.getElementById("avatar-input").addEventListener("input", (evt) => { document.getElementById("avatar-input").addEventListener("input", (evt) => {
if (!evt.target.files) return if (!evt.target.files) return
const data = new FormData(); const data = new FormData();