removed some deletes after token resetting

This commit is contained in:
Cam 2024-02-15 01:00:05 -06:00
parent fe9152c451
commit 1eac1ad941
No known key found for this signature in database
GPG Key ID: 367B7C7EBD84A8BD
13 changed files with 109 additions and 112 deletions

View File

@ -2,6 +2,7 @@ package controller
import ( import (
"github.com/go-openapi/runtime/middleware" "github.com/go-openapi/runtime/middleware"
"github.com/openziti/zrok/rest_model_zrok"
"github.com/openziti/zrok/rest_server_zrok/operations/account" "github.com/openziti/zrok/rest_server_zrok/operations/account"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -12,7 +13,7 @@ func newResetTokenHandler() *resetTokenHandler {
return &resetTokenHandler{} return &resetTokenHandler{}
} }
func (handler *resetTokenHandler) Handle(params account.ResetTokenParams) middleware.Responder { func (handler *resetTokenHandler) Handle(params account.ResetTokenParams, principal *rest_model_zrok.Principal) middleware.Responder {
if params.Body.EmailAddress == "" { if params.Body.EmailAddress == "" {
logrus.Error("missing email") logrus.Error("missing email")
return account.NewResetTokenNotFound() return account.NewResetTokenNotFound()
@ -37,7 +38,7 @@ func (handler *resetTokenHandler) Handle(params account.ResetTokenParams) middle
} }
// Need to create new token and invalidate all other resources // Need to create new token and invalidate all other resources
token, err := createToken() token, err := CreateToken()
if err != nil { if err != nil {
logrus.Errorf("error creating token for request '%v': %v", params.Body.EmailAddress, err) logrus.Errorf("error creating token for request '%v': %v", params.Body.EmailAddress, err)
return account.NewResetTokenInternalServerError() return account.NewResetTokenInternalServerError()
@ -50,23 +51,6 @@ func (handler *resetTokenHandler) Handle(params account.ResetTokenParams) middle
return account.NewResetTokenInternalServerError() return account.NewResetTokenInternalServerError()
} }
if err := str.DeletePasswordResetRequestByAccountId(a.Id, tx); err != nil {
logrus.Errorf("error deleting password reset requests for request '%v', but continuing on: %v", params.Body.EmailAddress, err)
}
environmentIds, err := str.DeleteEnvironmentByAccountID(a.Id, tx)
if err != nil {
logrus.Errorf("error deleting environments for request '%v', but continuing on: %v", params.Body.EmailAddress, err)
}
if err := str.DeleteFrontendsByEnvironmentIds(tx, environmentIds...); err != nil {
logrus.Errorf("error deleting frontends for request '%v', but continuing on: %v", params.Body.EmailAddress, err)
}
if err := str.DeleteSharesByEnvironmentIds(tx, environmentIds...); err != nil {
logrus.Errorf("error deleting shares for request '%v', but continuing on: %v", params.Body.EmailAddress, err)
}
if err := tx.Commit(); err != nil { if err := tx.Commit(); err != nil {
logrus.Errorf("error committing '%v' (%v): %v", params.Body.EmailAddress, a.Email, err) logrus.Errorf("error committing '%v' (%v): %v", params.Body.EmailAddress, a.Email, err)
return account.NewResetTokenInternalServerError() return account.NewResetTokenInternalServerError()

View File

@ -82,23 +82,3 @@ func (str *Store) DeleteEnvironment(id int, tx *sqlx.Tx) error {
} }
return nil return nil
} }
func (str *Store) DeleteEnvironmentByAccountID(accountId int, tx *sqlx.Tx) ([]int, error) {
stmt, err := tx.Prepare("update environments set updated_at = current_timestamp, deleted = true where account_id = $1 returning id")
if err != nil {
return nil, errors.Wrap(err, "error preparing environments delete by account_id statement")
}
rows, err := stmt.Query(accountId)
if err != nil {
return nil, errors.Wrap(err, "error executing environments delete by account_id statement")
}
var is []int
for rows.Next() {
var i int
if err := rows.Scan(&i); err != nil {
return nil, errors.Wrap(err, "error scanning environment id")
}
is = append(is, i)
}
return is, nil
}

View File

@ -1,10 +1,8 @@
package store package store
import ( import (
"fmt"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/pkg/errors" "github.com/pkg/errors"
"strings"
) )
type Frontend struct { type Frontend struct {
@ -148,21 +146,3 @@ func (str *Store) DeleteFrontend(id int, tx *sqlx.Tx) error {
} }
return nil return nil
} }
func (str *Store) DeleteFrontendsByEnvironmentIds(tx *sqlx.Tx, environmentIds ...int) error {
queryStrs := make([]string, 0, len(environmentIds))
queryVals := make([]interface{}, 0, len(environmentIds))
for i, v := range environmentIds {
queryStrs = append(queryStrs, fmt.Sprintf("$%d", i))
queryVals = append(queryVals, v)
}
stmt, err := tx.Prepare(fmt.Sprintf("update frontends set updated_at = current_timestamp, deleted = true where environment_id in (%s)", strings.Join(queryStrs, ",")))
if err != nil {
return errors.Wrap(err, "error preparing frontends delete by environment_id statement")
}
_, err = stmt.Exec(queryVals...)
if err != nil {
return errors.Wrap(err, "error executing frontends delete by environment_id statement")
}
return nil
}

View File

@ -98,15 +98,3 @@ func (str *Store) DeleteMultiplePasswordResetRequests(ids []int, tx *sqlx.Tx) er
} }
return nil return nil
} }
func (str *Store) DeletePasswordResetRequestByAccountId(accountId int, tx *sqlx.Tx) error {
stmt, err := tx.Prepare("update password_reset_requests set updated_at = current_timestamp, deleted = true where account_id = $1")
if err != nil {
return errors.Wrap(err, "error preparing password_reset_requests by account_id delete statement")
}
_, err = stmt.Exec(accountId)
if err != nil {
return errors.Wrap(err, "error executing password_reset_requests by account_id delete statement")
}
return nil
}

View File

@ -1,10 +1,8 @@
package store package store
import ( import (
"fmt"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/pkg/errors" "github.com/pkg/errors"
"strings"
) )
type Share struct { type Share struct {
@ -113,21 +111,3 @@ func (str *Store) DeleteShare(id int, tx *sqlx.Tx) error {
} }
return nil return nil
} }
func (str *Store) DeleteSharesByEnvironmentIds(tx *sqlx.Tx, environmentIds ...int) error {
queryStrs := make([]string, 0, len(environmentIds))
queryVals := make([]interface{}, 0, len(environmentIds))
for i, v := range environmentIds {
queryStrs = append(queryStrs, fmt.Sprintf("$%d", i))
queryVals = append(queryVals, v)
}
stmt, err := tx.Prepare(fmt.Sprintf("update shares set updated_at = current_timestamp, deleted = true where environment_id in (%s)", strings.Join(queryStrs, ",")))
if err != nil {
return errors.Wrap(err, "error preparing Shares delete by environment_id statement")
}
_, err = stmt.Exec(queryVals...)
if err != nil {
return errors.Wrap(err, "error executing Shares delete by environment_id statement")
}
return nil
}

View File

@ -40,7 +40,7 @@ type ClientService interface {
ResetPasswordRequest(params *ResetPasswordRequestParams, opts ...ClientOption) (*ResetPasswordRequestCreated, error) ResetPasswordRequest(params *ResetPasswordRequestParams, opts ...ClientOption) (*ResetPasswordRequestCreated, error)
ResetToken(params *ResetTokenParams, opts ...ClientOption) (*ResetTokenOK, error) ResetToken(params *ResetTokenParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ResetTokenOK, error)
Verify(params *VerifyParams, opts ...ClientOption) (*VerifyOK, error) Verify(params *VerifyParams, opts ...ClientOption) (*VerifyOK, error)
@ -240,7 +240,7 @@ func (a *Client) ResetPasswordRequest(params *ResetPasswordRequestParams, opts .
/* /*
ResetToken reset token API ResetToken reset token API
*/ */
func (a *Client) ResetToken(params *ResetTokenParams, opts ...ClientOption) (*ResetTokenOK, error) { func (a *Client) ResetToken(params *ResetTokenParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ResetTokenOK, error) {
// TODO: Validate the params before sending // TODO: Validate the params before sending
if params == nil { if params == nil {
params = NewResetTokenParams() params = NewResetTokenParams()
@ -254,6 +254,7 @@ func (a *Client) ResetToken(params *ResetTokenParams, opts ...ClientOption) (*Re
Schemes: []string{"http"}, Schemes: []string{"http"},
Params: params, Params: params,
Reader: &ResetTokenReader{formats: a.formats}, Reader: &ResetTokenReader{formats: a.formats},
AuthInfo: authInfo,
Context: params.Context, Context: params.Context,
Client: params.HTTPClient, Client: params.HTTPClient,
} }

View File

@ -834,6 +834,11 @@ func init() {
}, },
"/resetToken": { "/resetToken": {
"post": { "post": {
"security": [
{
"key": []
}
],
"tags": [ "tags": [
"account" "account"
], ],
@ -2497,6 +2502,11 @@ func init() {
}, },
"/resetToken": { "/resetToken": {
"post": { "post": {
"security": [
{
"key": []
}
],
"tags": [ "tags": [
"account" "account"
], ],

View File

@ -12,19 +12,21 @@ import (
"github.com/go-openapi/runtime/middleware" "github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/strfmt" "github.com/go-openapi/strfmt"
"github.com/go-openapi/swag" "github.com/go-openapi/swag"
"github.com/openziti/zrok/rest_model_zrok"
) )
// ResetTokenHandlerFunc turns a function with the right signature into a reset token handler // ResetTokenHandlerFunc turns a function with the right signature into a reset token handler
type ResetTokenHandlerFunc func(ResetTokenParams) middleware.Responder type ResetTokenHandlerFunc func(ResetTokenParams, *rest_model_zrok.Principal) middleware.Responder
// Handle executing the request and returning a response // Handle executing the request and returning a response
func (fn ResetTokenHandlerFunc) Handle(params ResetTokenParams) middleware.Responder { func (fn ResetTokenHandlerFunc) Handle(params ResetTokenParams, principal *rest_model_zrok.Principal) middleware.Responder {
return fn(params) return fn(params, principal)
} }
// ResetTokenHandler interface for that can handle valid reset token params // ResetTokenHandler interface for that can handle valid reset token params
type ResetTokenHandler interface { type ResetTokenHandler interface {
Handle(ResetTokenParams) middleware.Responder Handle(ResetTokenParams, *rest_model_zrok.Principal) middleware.Responder
} }
// NewResetToken creates a new http.Handler for the reset token operation // NewResetToken creates a new http.Handler for the reset token operation
@ -48,12 +50,25 @@ func (o *ResetToken) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
*r = *rCtx *r = *rCtx
} }
var Params = NewResetTokenParams() var Params = NewResetTokenParams()
uprinc, aCtx, err := o.Context.Authorize(r, route)
if err != nil {
o.Context.Respond(rw, r, route.Produces, route, err)
return
}
if aCtx != nil {
*r = *aCtx
}
var principal *rest_model_zrok.Principal
if uprinc != nil {
principal = uprinc.(*rest_model_zrok.Principal) // this is really a rest_model_zrok.Principal, I promise
}
if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
o.Context.Respond(rw, r, route.Produces, route, err) o.Context.Respond(rw, r, route.Produces, route, err)
return return
} }
res := o.Handler.Handle(Params) // actually handle the request res := o.Handler.Handle(Params, principal) // actually handle the request
o.Context.Respond(rw, r, route.Produces, route, res) o.Context.Respond(rw, r, route.Produces, route, res)
} }

View File

@ -115,7 +115,7 @@ func NewZrokAPI(spec *loads.Document) *ZrokAPI {
AccountResetPasswordRequestHandler: account.ResetPasswordRequestHandlerFunc(func(params account.ResetPasswordRequestParams) middleware.Responder { AccountResetPasswordRequestHandler: account.ResetPasswordRequestHandlerFunc(func(params account.ResetPasswordRequestParams) middleware.Responder {
return middleware.NotImplemented("operation account.ResetPasswordRequest has not yet been implemented") return middleware.NotImplemented("operation account.ResetPasswordRequest has not yet been implemented")
}), }),
AccountResetTokenHandler: account.ResetTokenHandlerFunc(func(params account.ResetTokenParams) middleware.Responder { AccountResetTokenHandler: account.ResetTokenHandlerFunc(func(params account.ResetTokenParams, principal *rest_model_zrok.Principal) middleware.Responder {
return middleware.NotImplemented("operation account.ResetToken has not yet been implemented") return middleware.NotImplemented("operation account.ResetToken has not yet been implemented")
}), }),
ShareShareHandler: share.ShareHandlerFunc(func(params share.ShareParams, principal *rest_model_zrok.Principal) middleware.Responder { ShareShareHandler: share.ShareHandlerFunc(func(params share.ShareParams, principal *rest_model_zrok.Principal) middleware.Responder {

View File

@ -568,7 +568,7 @@ class AccountApi(object):
['application/zrok.v1+json']) # noqa: E501 ['application/zrok.v1+json']) # noqa: E501
# Authentication setting # Authentication setting
auth_settings = [] # noqa: E501 auth_settings = ['key'] # noqa: E501
return self.api_client.call_api( return self.api_client.call_api(
'/resetToken', 'POST', '/resetToken', 'POST',

View File

@ -125,6 +125,8 @@ paths:
post: post:
tags: tags:
- account - account
security:
- key: []
operationId: resetToken operationId: resetToken
parameters: parameters:
- name: body - name: body

View File

@ -140,7 +140,12 @@ const resetPasswordRequestOperation = {
const resetTokenOperation = { const resetTokenOperation = {
path: '/resetToken', path: '/resetToken',
contentTypes: ['application/zrok.v1+json'], contentTypes: ['application/zrok.v1+json'],
method: 'post' method: 'post',
security: [
{
id: 'key'
}
]
} }
const verifyOperation = { const verifyOperation = {

View File

@ -1,8 +1,26 @@
import React, {useRef, useState} from "react";
import Modal from "react-bootstrap/Modal"; import Modal from "react-bootstrap/Modal";
import { Button } from "react-bootstrap"; import {mdiContentCopy} from "@mdi/js";
import Icon from "@mdi/react";
import { Button, Overlay, Tooltip } from "react-bootstrap";
import * as account from "../../../../api/account"; import * as account from "../../../../api/account";
const ResetToken = (props) => { const ResetToken = (props) => {
const target = useRef(null);
const [showTooltip, setShowTooltip] = useState(false);
const handleCopy = async () => {
let copiedText = document.getElementById("zrok-token").innerHTML;
try {
await navigator.clipboard.writeText(copiedText);
setShowTooltip(true);
setTimeout(() => setShowTooltip(false), 1000);
} catch(err) {
console.error("failed to copy", err);
}
}
let resetToken = () => { let resetToken = () => {
console.log("I should reset my token") console.log("I should reset my token")
@ -14,26 +32,60 @@ const ResetToken = (props) => {
"token": resp.data.token "token": resp.data.token
})); }));
document.dispatchEvent(new Event('storage')) document.dispatchEvent(new Event('storage'))
setModalBody((
<div>
<p>You will need to update your environment file ($HOME/.zrok/environmetn.json)</p>
Token: <span id={"zrok-token"}>{resp.data.token}</span>{' '}
<Icon ref={target} path={mdiContentCopy} size={0.7} onClick={handleCopy}/>
</div>
));
setModalHeader((
<span>Token Reset Successful</span>
))
}).catch(err => { }).catch(err => {
console.log("err", err); console.log("err", err);
}); });
props.onHide();
} }
let hide = () => {
setModalBody(defaultModal)
props.onHide()
}
let defaultHeader = (<span>WARNING - Are you Sure?</span>)
let defaultModal = (
<div>
<div>
<div>Reseting your token will revoke access from any CLI environments.</div>
<div>You will need to update $HOME/.zrok/environments.yml with your new token.</div>
</div>
<div style={{display: 'flex', alignItems:'center', justifyContent: 'center'}}>
<Button variant={"light"} onClick={resetToken}>Reset Token</Button>
<Button variant={"dark"} onClick={props.onHide}>Cancel</Button>
</div>
</div>
);
const [modalBody, setModalBody] = useState(defaultModal);
const [modalHeader, setModalHeader] = useState(defaultHeader);
return ( return (
<div> <div>
<Modal show={props.show} onHide={props.onHide} centered> <Modal show={props.show} onHide={hide} centered>
<Modal.Header closeButton>WARNING - Are you Sure?</Modal.Header> <Modal.Header closeButton>{modalHeader}</Modal.Header>
<Modal.Body> <Modal.Body>
<div> {modalBody}
Reseting your token will remove all environments, frontends, and shares you've created.
</div>
<div style={{display: 'flex', alignItems:'center', justifyContent: 'center'}}>
<Button variant={"light"} onClick={resetToken}>Reset Password</Button>
<Button variant={"dark"} onClick={props.onHide}>Cancel</Button>
</div>
</Modal.Body> </Modal.Body>
</Modal> </Modal>
<Overlay target={target.current} show={showTooltip} placement={"bottom"}>
{(props) => (
<Tooltip id={"copy-tooltip"} {...props}>
Copied!
</Tooltip>
)}
</Overlay>
</div> </div>
) )
} }