-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
(BEDS-848) Move search and cursor parameter validation to API #1014
base: staging
Are you sure you want to change the base?
Conversation
func (s VDBBlocksSearches) GetSearches() []SearchType { | ||
return []SearchType{ | ||
Integer, | ||
ValidatorPublicKeyWithPrefix, | ||
Name, | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed, we don't really need to provide a list of search types if we always check against every search type and just ignore them in SetSearchType
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's optional now
@@ -170,6 +170,35 @@ var VDBBlocksColumns = struct { | |||
VDBBlockProposerReward, | |||
} | |||
|
|||
type VDBBlocksSearches struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't know if these structs fit in the enum package. But also don't know where else they'd fit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved it to types
, I think that's slightly better, ptal
@@ -416,6 +435,17 @@ func checkSort[T enums.EnumFactory[T]](v *validationError, sortString string) *t | |||
return &types.Sort[T]{Column: sortCol, Desc: desc} | |||
} | |||
|
|||
func checkSearch[T enums.Searchable](searchString string) (T, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This func should prob never return an error, in worst case the returning searchable should be empty
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's returning a bool now to indicate an invalid search (if false
), aka the search query didn't match the rules for this search. This includes accepted pattern matching but it may also check extra conditions. E.g. if the aggregateGroups
flag is set, the group search is not applied even if the regex would otherwise match. See the three current examples, e.g. https://github.com/gobitfly/beaconchain/pull/1014/files#diff-eeb9062bd8258c1d32e584699f9dc786ad81df60981ec50fbc17b3c8962d7581R666-R669
Motivation for this approach was to allow early-outing with empty responses on the api layer already if possible, before even invoking data access at all.
backend/pkg/api/enums/enums.go
Outdated
Name SearchType = iota // default | ||
Integer | ||
EthereumAddress | ||
WithdrawalCredential | ||
EnsName | ||
NonEmpty | ||
Graffiti | ||
Cursor | ||
Password | ||
EmailUserToken | ||
JsonContentType | ||
// Validator Dashboard | ||
ValidatorDashboardPublicId | ||
ValidatorPublicKeyWithPrefix | ||
ValidatorPublicKey |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since const namespace is package-scoped, pls prefix these enums with SearchType...
, like with the other enums.
Deploying beaconchain with Cloudflare Pages
|
cd7032b
to
6a12467
Compare
@@ -267,6 +267,10 @@ func writeResponse(w http.ResponseWriter, r *http.Request, statusCode int, respo | |||
} | |||
} | |||
|
|||
func emptyPagingResponse() interface{} { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
func emptyPagingResponse() interface{} { | |
func emptyPagingResponse() types.ApiPagingResponse[any] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be better if we seperate the types here. Cursors should probably go in their own cursor.go
, and searches should also probably get their own. We prob have to find some good naming to differentiate between the search endpoint and the search filters on tables.
data, paging, err := h.getDataAccessor(r).GetValidatorDashboardValidators(r.Context(), *dashboardId, groupId, pagingParams.cursor, *sort, pagingParams.search, pagingParams.limit) | ||
search := &types.VDBManageValidatorsSearch{DashboardId: *dashboardId} | ||
if !checkSearch(search, pagingParams.search) { | ||
returnOk(w, r, emptyPagingResponse()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs a return statement after this (also for all other checkSearch
calls)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should maybe also discuss with team whether we want to early return, ignore, or return error (if you did and this was the conclusion please lmk)
backend/pkg/api/types/data_access.go
Outdated
type SearchNumber baseSearchResult[uint64] | ||
type SearchString baseSearchResult[string] | ||
|
||
func (bs *basicSearch) AsNumber(st SearchType) SearchNumber { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't get why this needs to have a SearchType
argument, feels like it unnecessarily complicates the API of using searchtypes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was meant to enable increased but unified flexibility in case that different types should be returned in different formats, e.g. to scale ETH -> wei values or something. Atm I also can't think of many examples (removing/adding an optional 0x
prefix could be one though), so it's true that this looks like unneeded overhead, didn't think it's a big issue as this is encapsulated away from every-day data access workflow. But I'll disable it for now until a real usecase comes up
backend/pkg/api/types/data_access.go
Outdated
case SearchTypeInteger: | ||
number, err := strconv.ParseUint(bs.value, 10, 64) | ||
if err != nil { | ||
log.Error(err, "error converting search value, check regex parsing", 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should definitely return the error and not just log it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to explicitly design the entire validation process in a way that api handles errors early so that data access doesn't have to deal with catching anymore at the point of using the result, as this is kind of the point of everything and greatly improves readability. Converting the raw string result to the expected format should happen earlier though, I'll try to revert back to using struct fields instead of methods
backend/pkg/api/types/data_access.go
Outdated
return SearchNumber{} | ||
} | ||
|
||
func (bs *basicSearch) AsString(st SearchType) SearchString { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, I think the SearchTypes
arg makes this more complicated than necessary. I think in practice the data access func would rather just want to have a .GetValue()
and format the value itself rather than have something funky happening hidden behind a AsString()
. If it turns out we want to reuse formatting logic, it should happen in another func IMO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay I've removed these methods and gone a step in that direction, ptal. Wouldn't remove the conversion entirely as doing it separately requires error handling in data access which would be a form of input validation.
|
||
data, paging, err := h.getDataAccessor(r).GetValidatorDashboardSummary(r.Context(), *dashboardId, period, pagingParams.cursor, *sort, pagingParams.search, pagingParams.limit, protocolModes) | ||
data, paging, err := h.getDataAccessor(r).GetValidatorDashboardSummary(r.Context(), *dashboardId, period, "", *sort, *search, pagingParams.limit, protocolModes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is passing the ""
intentional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes basically, atleast until we decided what to do here: https://github.com/gobitfly/beaconchain/pull/1014/files#diff-bc69fc9b7d7d8ba0514ef4cf9cb7f09971cb7860fd7460d0dc6e3ebeb76e7b1bR31
import ( | ||
"time" | ||
) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: could remove this change
SearchTypePassword | ||
SearchTypeEmailUserToken | ||
SearchTypeJsonContentType |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are these valid search types?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are not, just copied all regexes for now
backend/pkg/api/data_access/vdb.go
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For all changes within data access you'd probably want to get the direct opinion of data access team members. For now in total this PR adds more lines than it removes, so currently it's achieving the same thing with more lines. BUT it's good and necessary, that the cursor validation happens in handlers, not in data access. I don't know whether you've applied these search type changes everywhere or if it will scale better in future (e.g. with account dashboard). So I can't form a full opinion here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah you're right, I'll also ask other members. Types haven't been applied everywhere yet, will do so next; imo it simplifies things but the changes also need thorough testing
6a12467
to
3a15cf4
Compare
8e79e8f
to
2acc450
Compare
No description provided.