mirror of
https://github.com/PrivateCaptcha/PrivateCaptcha.git
synced 2026-02-09 15:28:49 -06:00
Add API to get a single property. related PrivateCaptcha/issues#45
This commit is contained in:
@@ -742,3 +742,47 @@ func (s *Server) getOrgProperties(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
s.sendAPISuccessResponseEx(ctx, response, w, cacheHeaders)
|
||||
}
|
||||
|
||||
func (s *Server) getOrgProperty(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
user, _, err := s.requestUser(ctx)
|
||||
if err != nil {
|
||||
s.sendHTTPErrorResponse(err, w)
|
||||
return
|
||||
}
|
||||
|
||||
org, err := s.requestOrg(user, r, false /*only owner*/)
|
||||
if err != nil {
|
||||
if err == db.ErrInvalidInput {
|
||||
s.sendAPIErrorResponse(ctx, common.StatusOrgIDInvalidError, r, w)
|
||||
} else {
|
||||
s.sendHTTPErrorResponse(err, w)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
property, err := s.requestProperty(org, r)
|
||||
if err != nil {
|
||||
if err == db.ErrSoftDeleted {
|
||||
s.sendAPIErrorResponse(ctx, common.StatusPropertyIDInvalidError, r, w)
|
||||
} else {
|
||||
s.sendHTTPErrorResponse(err, w)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
data := &apiPropertyOutput{
|
||||
ID: s.IDHasher.Encrypt(int(property.ID)),
|
||||
Name: property.Name,
|
||||
Domain: property.Domain,
|
||||
Sitekey: db.UUIDToSiteKey(property.ExternalID),
|
||||
Level: int(property.Level.Int16),
|
||||
Growth: string(property.Growth),
|
||||
ValiditySeconds: int(property.ValidityInterval.Seconds()),
|
||||
AllowSubdomains: property.AllowSubdomains,
|
||||
AllowLocalhost: property.AllowLocalhost,
|
||||
MaxReplayCount: int(property.MaxReplayCount),
|
||||
}
|
||||
|
||||
s.sendAPISuccessResponse(ctx, data, w)
|
||||
}
|
||||
|
||||
@@ -634,3 +634,109 @@ func TestApiGetProperties(t *testing.T) {
|
||||
t.Fatalf("Unexpected number of properties: %v", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestApiGetProperty(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
|
||||
ctx := common.TraceContext(t.Context(), t.Name())
|
||||
|
||||
user, org, apiKey, err := setupAPISuite(ctx, t.Name())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
property, _, err := s.BusinessDB.Impl().CreateNewProperty(ctx, db_test.CreateNewPropertyParams(user.ID, "example.com"), org)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
propertyID := s.IDHasher.Encrypt(int(property.ID))
|
||||
output, meta, err := requestResponseAPISuite[*apiPropertyOutput](ctx, nil,
|
||||
http.MethodGet,
|
||||
fmt.Sprintf("/%s/%s/%s/%s", common.OrgEndpoint, s.IDHasher.Encrypt(int(org.ID)),
|
||||
common.PropertyEndpoint, propertyID),
|
||||
apiKey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !meta.Code.Success() {
|
||||
t.Fatalf("Unexpected status code: %v", meta.Description)
|
||||
}
|
||||
|
||||
if output.ID != propertyID {
|
||||
t.Errorf("Received property ID %v but %v expected", output.ID, property.ID)
|
||||
}
|
||||
|
||||
if output.Name != property.Name {
|
||||
t.Errorf("Received property Name %v, but %v expected", output.Name, property.Name)
|
||||
}
|
||||
|
||||
if output.Sitekey != db.UUIDToSiteKey(property.ExternalID) {
|
||||
t.Errorf("Unexpected property sitekey: %v", output.Sitekey)
|
||||
}
|
||||
|
||||
if output.Level != int(property.Level.Int16) {
|
||||
t.Errorf("Received property Level %v but %v expected", output.Level, property.Level.Int16)
|
||||
}
|
||||
|
||||
if output.Growth != string(property.Growth) {
|
||||
t.Errorf("Received property Growth %v but %v expected", output.Growth, property.Growth)
|
||||
}
|
||||
|
||||
if output.ValiditySeconds != int(property.ValidityInterval.Seconds()) {
|
||||
t.Errorf("Received property Validity Seconds %v but %v expected", output.ValiditySeconds, property.ValidityInterval.Seconds())
|
||||
}
|
||||
|
||||
if output.AllowSubdomains != property.AllowSubdomains {
|
||||
t.Errorf("Received property Subdomains %v but %v expected", output.AllowSubdomains, property.AllowSubdomains)
|
||||
}
|
||||
|
||||
if output.AllowLocalhost != property.AllowLocalhost {
|
||||
t.Errorf("Received property Localhost %v but %v expected", output.AllowLocalhost, property.AllowLocalhost)
|
||||
}
|
||||
|
||||
if output.MaxReplayCount != int(property.MaxReplayCount) {
|
||||
t.Errorf("Received property MaxReplayCount %v but %v expected", output.MaxReplayCount, property.MaxReplayCount)
|
||||
}
|
||||
}
|
||||
|
||||
func TestApiGetPropertyPermissions(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
|
||||
ctx := common.TraceContext(t.Context(), t.Name())
|
||||
|
||||
owner, org, _, err := setupAPISuite(ctx, t.Name())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
property, _, err := s.BusinessDB.Impl().CreateNewProperty(ctx, db_test.CreateNewPropertyParams(owner.ID, "example.com"), org)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, _, apiKey, err := setupAPISuite(ctx, t.Name()+"_user2")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
propertyID := s.IDHasher.Encrypt(int(property.ID))
|
||||
|
||||
resp, err := apiRequestSuite(ctx, nil,
|
||||
http.MethodGet,
|
||||
fmt.Sprintf("/%s/%s/%s/%s", common.OrgEndpoint, s.IDHasher.Encrypt(int(org.ID)),
|
||||
common.PropertyEndpoint, propertyID),
|
||||
apiKey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusForbidden {
|
||||
t.Fatalf("Unexpected status code: %v", resp.StatusCode)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,3 +69,16 @@ type apiAsyncTaskResultOutput struct {
|
||||
Finished bool `json:"finished"`
|
||||
Result interface{} `json:"result"`
|
||||
}
|
||||
|
||||
type apiPropertyOutput struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Domain string `json:"domain"`
|
||||
Sitekey string `json:"sitekey"`
|
||||
Level int `json:"level,omitempty"`
|
||||
Growth string `json:"growth,omitempty"`
|
||||
ValiditySeconds int `json:"validity_seconds,omitempty"`
|
||||
AllowSubdomains bool `json:"allow_subdomains,omitempty"`
|
||||
AllowLocalhost bool `json:"allow_localhost,omitempty"`
|
||||
MaxReplayCount int `json:"max_replay_count,omitempty"`
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ func (s *Server) setupEnterprise(rg *common.RouteGenerator, publicChain alice.Ch
|
||||
rg.Handle(rg.Post(common.OrgEndpoint, arg(common.ParamOrg), common.PropertiesEndpoint), portalAPIChain, http.MaxBytesHandler(http.HandlerFunc(s.postNewProperties), maxPostPropertiesBodySize))
|
||||
rg.Handle(rg.Delete(common.PropertiesEndpoint), portalAPIChain, http.MaxBytesHandler(http.HandlerFunc(s.deleteProperties), maxDeletePropertiesBodySize))
|
||||
rg.Handle(rg.Patch(common.PropertiesEndpoint), portalAPIChain, http.MaxBytesHandler(http.HandlerFunc(s.updateProperties), maxUpdatePropertiesBodySize))
|
||||
rg.Handle(rg.Get(common.OrgEndpoint, arg(common.ParamOrg), common.PropertyEndpoint, arg(common.ParamProperty)), portalAPIChain, http.HandlerFunc(s.getOrgProperty))
|
||||
}
|
||||
|
||||
func (s *Server) RegisterTaskHandlers(ctx context.Context) {
|
||||
@@ -98,6 +99,23 @@ func (s *Server) requestOrg(user *dbgen.User, r *http.Request, onlyOwner bool) (
|
||||
return org, nil
|
||||
}
|
||||
|
||||
func (s *Server) requestProperty(org *dbgen.Organization, r *http.Request) (*dbgen.Property, error) {
|
||||
ctx := r.Context()
|
||||
|
||||
propertyID, value, err := common.IntPathArg(r, common.ParamProperty, s.IDHasher)
|
||||
if err != nil {
|
||||
slog.ErrorContext(ctx, "Failed to parse property path parameter", "value", value, common.ErrAttr(err))
|
||||
return nil, db.ErrInvalidInput
|
||||
}
|
||||
|
||||
property, err := s.BusinessDB.Impl().RetrieveOrgProperty(ctx, org, propertyID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return property, nil
|
||||
}
|
||||
|
||||
func (s *Server) sendHTTPErrorResponse(err error, w http.ResponseWriter) {
|
||||
switch err {
|
||||
case db.ErrRecordNotFound:
|
||||
|
||||
Reference in New Issue
Block a user