mirror of
https://github.com/binwiederhier/ntfy.git
synced 2026-01-18 16:17:26 +01:00
Disallow changing provisioned user and tokens
This commit is contained in:
@@ -85,6 +85,7 @@ func (s *Server) handleAccountGet(w http.ResponseWriter, r *http.Request, v *vis
|
||||
response.Username = u.Name
|
||||
response.Role = string(u.Role)
|
||||
response.SyncTopic = u.SyncTopic
|
||||
response.Provisioned = u.Provisioned
|
||||
if u.Prefs != nil {
|
||||
if u.Prefs.Language != nil {
|
||||
response.Language = *u.Prefs.Language
|
||||
@@ -139,11 +140,12 @@ func (s *Server) handleAccountGet(w http.ResponseWriter, r *http.Request, v *vis
|
||||
lastOrigin = t.LastOrigin.String()
|
||||
}
|
||||
response.Tokens = append(response.Tokens, &apiAccountTokenResponse{
|
||||
Token: t.Value,
|
||||
Label: t.Label,
|
||||
LastAccess: t.LastAccess.Unix(),
|
||||
LastOrigin: lastOrigin,
|
||||
Expires: t.Expires.Unix(),
|
||||
Token: t.Value,
|
||||
Label: t.Label,
|
||||
LastAccess: t.LastAccess.Unix(),
|
||||
LastOrigin: lastOrigin,
|
||||
Expires: t.Expires.Unix(),
|
||||
Provisioned: t.Provisioned,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,11 +360,12 @@ type apiAccountTokenUpdateRequest struct {
|
||||
}
|
||||
|
||||
type apiAccountTokenResponse struct {
|
||||
Token string `json:"token"`
|
||||
Label string `json:"label,omitempty"`
|
||||
LastAccess int64 `json:"last_access,omitempty"`
|
||||
LastOrigin string `json:"last_origin,omitempty"`
|
||||
Expires int64 `json:"expires,omitempty"` // Unix timestamp
|
||||
Token string `json:"token"`
|
||||
Label string `json:"label,omitempty"`
|
||||
LastAccess int64 `json:"last_access,omitempty"`
|
||||
LastOrigin string `json:"last_origin,omitempty"`
|
||||
Expires int64 `json:"expires,omitempty"` // Unix timestamp
|
||||
Provisioned bool `json:"provisioned,omitempty"` // True if this token was provisioned by the server config
|
||||
}
|
||||
|
||||
type apiAccountPhoneNumberVerifyRequest struct {
|
||||
@@ -426,6 +427,7 @@ type apiAccountResponse struct {
|
||||
Username string `json:"username"`
|
||||
Role string `json:"role,omitempty"`
|
||||
SyncTopic string `json:"sync_topic,omitempty"`
|
||||
Provisioned bool `json:"provisioned,omitempty"`
|
||||
Language string `json:"language,omitempty"`
|
||||
Notification *user.NotificationPrefs `json:"notification,omitempty"`
|
||||
Subscriptions []*user.Subscription `json:"subscriptions,omitempty"`
|
||||
|
||||
@@ -212,6 +212,7 @@
|
||||
"account_basics_phone_numbers_dialog_check_verification_button": "Confirm code",
|
||||
"account_basics_phone_numbers_dialog_channel_sms": "SMS",
|
||||
"account_basics_phone_numbers_dialog_channel_call": "Call",
|
||||
"account_basics_cannot_edit_or_delete_provisioned_user": "A provisioned user cannot be edited or deleted from the web app",
|
||||
"account_usage_title": "Usage",
|
||||
"account_usage_of_limit": "of {{limit}}",
|
||||
"account_usage_unlimited": "Unlimited",
|
||||
@@ -291,6 +292,7 @@
|
||||
"account_tokens_table_current_session": "Current browser session",
|
||||
"account_tokens_table_copied_to_clipboard": "Access token copied",
|
||||
"account_tokens_table_cannot_delete_or_edit": "Cannot edit or delete current session token",
|
||||
"account_tokens_table_cannot_delete_or_edit_provisioned_token": "Cannot edit or delete provisioned token",
|
||||
"account_tokens_table_create_token_button": "Create access token",
|
||||
"account_tokens_table_last_origin_tooltip": "From IP address {{ip}}, click to lookup",
|
||||
"account_tokens_dialog_title_create": "Create access token",
|
||||
|
||||
@@ -31,14 +31,6 @@ export class TopicReservedError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
export class ProvisionedUserPasswordError extends Error {
|
||||
static CODE = 40905; // errHTTPConflictTopicReserved
|
||||
|
||||
constructor() {
|
||||
super("Cannot change the password of a provisioned user");
|
||||
}
|
||||
}
|
||||
|
||||
export class AccountCreateLimitReachedError extends Error {
|
||||
static CODE = 42906; // errHTTPTooManyRequestsLimitAccountCreation
|
||||
|
||||
|
||||
@@ -100,15 +100,13 @@ const Username = () => {
|
||||
<Pref labelId={labelId} title={t("account_basics_username_title")} description={t("account_basics_username_description")}>
|
||||
<div aria-labelledby={labelId}>
|
||||
{session.username()}
|
||||
{account?.role === Role.ADMIN ? (
|
||||
{account?.role === Role.ADMIN && (
|
||||
<>
|
||||
{" "}
|
||||
<Tooltip title={t("account_basics_username_admin_tooltip")}>
|
||||
<span style={{ cursor: "default" }}>👑</span>
|
||||
</Tooltip>
|
||||
</>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</div>
|
||||
</Pref>
|
||||
@@ -119,6 +117,7 @@ const ChangePassword = () => {
|
||||
const { t } = useTranslation();
|
||||
const [dialogKey, setDialogKey] = useState(0);
|
||||
const [dialogOpen, setDialogOpen] = useState(false);
|
||||
const { account } = useContext(AccountContext);
|
||||
const labelId = "prefChangePassword";
|
||||
|
||||
const handleDialogOpen = () => {
|
||||
@@ -136,9 +135,19 @@ const ChangePassword = () => {
|
||||
<Typography color="gray" sx={{ float: "left", fontSize: "0.7rem", lineHeight: "3.5" }}>
|
||||
⬤⬤⬤⬤⬤⬤⬤⬤⬤⬤
|
||||
</Typography>
|
||||
<IconButton onClick={handleDialogOpen} aria-label={t("account_basics_password_description")}>
|
||||
<EditIcon />
|
||||
</IconButton>
|
||||
{!account?.provisioned ? (
|
||||
<IconButton onClick={handleDialogOpen} aria-label={t("account_basics_password_description")}>
|
||||
<EditIcon />
|
||||
</IconButton>
|
||||
) : (
|
||||
<Tooltip title={t("account_basics_cannot_edit_or_delete_provisioned_user")}>
|
||||
<span>
|
||||
<IconButton disabled>
|
||||
<EditIcon />
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
<ChangePasswordDialog key={`changePasswordDialog${dialogKey}`} open={dialogOpen} onClose={handleDialogClose} />
|
||||
</Pref>
|
||||
@@ -888,7 +897,7 @@ const TokensTable = (props) => {
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell align="right" sx={{ whiteSpace: "nowrap" }}>
|
||||
{token.token !== session.token() && (
|
||||
{token.token !== session.token() && !token.provisioned && (
|
||||
<>
|
||||
<IconButton onClick={() => handleEditClick(token)} aria-label={t("account_tokens_dialog_title_edit")}>
|
||||
<EditIcon />
|
||||
@@ -910,6 +919,18 @@ const TokensTable = (props) => {
|
||||
</span>
|
||||
</Tooltip>
|
||||
)}
|
||||
{token.provisioned && (
|
||||
<Tooltip title={t("account_tokens_table_cannot_delete_or_edit_provisioned_token")}>
|
||||
<span>
|
||||
<IconButton disabled>
|
||||
<EditIcon />
|
||||
</IconButton>
|
||||
<IconButton disabled>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
@@ -1048,6 +1069,7 @@ const DeleteAccount = () => {
|
||||
const { t } = useTranslation();
|
||||
const [dialogKey, setDialogKey] = useState(0);
|
||||
const [dialogOpen, setDialogOpen] = useState(false);
|
||||
const { account } = useContext(AccountContext);
|
||||
|
||||
const handleDialogOpen = () => {
|
||||
setDialogKey((prev) => prev + 1);
|
||||
@@ -1061,9 +1083,19 @@ const DeleteAccount = () => {
|
||||
return (
|
||||
<Pref title={t("account_delete_title")} description={t("account_delete_description")}>
|
||||
<div>
|
||||
<Button fullWidth={false} variant="outlined" color="error" startIcon={<DeleteOutlineIcon />} onClick={handleDialogOpen}>
|
||||
{t("account_delete_title")}
|
||||
</Button>
|
||||
{!account?.provisioned ? (
|
||||
<Button fullWidth={false} variant="outlined" color="error" startIcon={<DeleteOutlineIcon />} onClick={handleDialogOpen}>
|
||||
{t("account_delete_title")}
|
||||
</Button>
|
||||
) : (
|
||||
<Tooltip title={t("account_basics_cannot_edit_or_delete_provisioned_user")}>
|
||||
<span>
|
||||
<Button fullWidth={false} variant="outlined" color="error" startIcon={<DeleteOutlineIcon />} disabled>
|
||||
{t("account_delete_title")}
|
||||
</Button>
|
||||
</span>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
<DeleteAccountDialog key={`deleteAccountDialog${dialogKey}`} open={dialogOpen} onClose={handleDialogClose} />
|
||||
</Pref>
|
||||
|
||||
Reference in New Issue
Block a user