* Feat: return reasons why a feature evaluated to true or false
Note: this is very rough and just straight ripped from the nodejs
client. It will need a lot of work, but is a good place to start
* Feat: add suggested shape for new payload
* Chore: minor cleanup
* Wip: make server compile again
* Remove unused schema ref
* Export new schemas
* Chore: fix some tests to use sub property
* Fix: fix some tests
* Refactor: rename some variables, uncomment some stuff
* Add segments type to bootstrap options
* Add segments capability to offline feature evaluator
* Fix function calls after turning params into an option abject
* Feat: test strategy order, etc
* Feat: add test to check that all strats are returned correctly
* Feat: allow you to include strategy ids in clients
* Wip: hook up segments in the offline client.
Note: compared to regular clients, they still fail
* Feat: add segments validation
* Fix: fix test case invariant.
* Chore: revert to returning only `boolean` from strategies.
This _should_ make it work with custom strategies too 🤞
* Feat: make more properties of the returned feature required
* Wip: add some comments and unfinished tests for edge cases
* Feat: add `isEnabledInCurrentEnvironment` prop
* Feat: consider more strategy failure cases
* Feat: test that isenabledinenvironment matches expectations
* Feat: add unknown strategies
* Fix: fix property access typo
* Feat: add unknown strategy for fallback purposes
* Feat: test edge case: all unknown strategies
* Feat: add custom strategy to arbitrary
* Feat: test that features can be true, even if not enabled in env
* Chore: add some comments
* Wip: fix sdk tests
* Remove comments, improve test logging
* Feat: add descriptions and examples to playground feature schema
* Switch `examples` for `example`
* Update schemas with descriptions and examples
* Fix: update snapshot
* Fix: openapi example
* Fix: merge issues
* Fix: fix issue where feature evaluation state was wrong
* Chore: update openapi spec
* Fix: fix broken offline client tests
* Refactor: move schemas into separate files
* Refactor: remove "reason" for incomplete evaluation.
The only instances where evaluation is incomplete is when we don't
know what the strategy is.
* Refactor: move unleash node client into test and dev dependencies
* Wip: further removal of stuff
* Chore: remove a bunch of code that we don't use
* Chore: remove comment
* Chore: remove unused code
* Fix: fix some prettier errors
* Type parameters in strategies to avoid `any`
* Fix: remove commented out code
* Feat: make `id` required on playground strategies
* Chore: remove redundant type
* Fix: remove redundant if and fix fallback evaluation
* Refactor: reduce nesting and remove duplication
* Fix: remove unused helper function
* Refactor: type `parameters` as `unknown`
* Chore: remove redundant comment
* Refactor: move constraint code into a separate file
* Refactor: rename `unleash` -> `feature-evaluator`
* Rename class `Unleash` -> `FeatureEvaluator`
* Refactor: remove this.ready and sync logic from feature evaluator
* Refactor: remove unused code, rename config type
* Refactor: remove event emission from the Unleash client
* Remove unlistened-for events in feature evaluator
* Refactor: make offline client synchronous; remove code
* Fix: update openapi snapshot after adding required strategy ids
* Feat: change `strategies` format.
This commit changes the format of a playground feature's `strategies`
properties from a list of strategies to an object with properties
`result` and `data`. It looks a bit like this:
```ts
type Strategies = {
result: boolean | "unknown",
data: Strategy[]
}
```
The reason is that this allows us to avoid the breaking change that
was previously suggested in the PR:
`feature.isEnabled` used to be a straight boolean. Then, when we found
out we couldn't necessarily evaluate all strategies (custom strats are
hard!) we changed it to `boolean | 'unevaluated'`. However, this is
confusing on a few levels as the playground results are no longer the
same as the SDK would be, nor are they strictly boolean anymore.
This change reverts the `isEnabled` functionality to what it was
before (so it's always a mirror of what the SDK would show).
The equivalent of `feature.isEnabled === 'unevaluated'` now becomes
`feature.isEnabled && strategy.result === 'unknown'`.
* Fix: Fold long string descriptions over multiple lines.
* Fix: update snapshot after adding line breaks to descriptions
* Wip: fix openapi spec
* Feat: add openapi enforcer for enforcing the generated schema
* Chore: Allow the example keyword in params
* Feat: add validator tests and fix some errors
* Use @apidevtools/swagger-parser for schema validation
* Wip: refactor tests for updated schema name
* Feat: update request params creation method
* Feat: add query params to state
* Refactor: move mapping test into separate function
* Refactor: rename request-parameters -> query-parameters
* Refactor: expose only finished query parameters
* Wip: fixup param types
* Refactor: remove unused types
* Chore: rename and cleanup
* Chore: cleanup
* Fix: Update snapshot
* Fix: use ?? Instead of paramToBool to get defaults
* Wip: generate query param object type from openapi params list
* Wip: use generated types for export query params
* Revert "Fix: use ?? Instead of paramToBool to get defaults"
This reverts commit 842567500b.
Because we accept bools, strings, and numbers, this is the only way to
do it.
* Chore: update and pin json-schema-to-ts
* Fix: use `&` to merge types
* Update snapshot
* Chore: rename export-parameters-schema -> export-query-parameters
When it ends in `schema`, the tests expect it to be included in the
openapi index file.
* strategy sort order endpoint
Co-authored-by: Fredrik Strand Oseberg <fredrik.no@gmail.com>
* feat: add e2e test for happy path
* add tests to features strategies order
Co-authored-by: Fredrik Strand Oseberg <fredrik.no@gmail.com>
* feat: add tests for sort-order
* fix: update snapshot
* fix: lint
Co-authored-by: Fredrik Strand Oseberg <fredrik.no@gmail.com>
* Implement user grouping feature for permissions
Co-authored-by: Thomas Heartman <thomas@getunleash.ai>
Co-authored-by: Jaanus Sellin <sellinjaanus@gmail.com>
Co-authored-by: Nuno Góis <github@nunogois.com>
Co-authored-by: Thomas Heartman <thomas@getunleash.ai>
* Refactor: use the `ALL` constant for tests
* Fix: context is not passed to `getVariant` call
This commit fixes a bug wherein a toggle with variants would show as
enabled but without variants. This was because the `getVariant` call
didn't receive the provided context as an argument.
* Chore: add unleash-client dependency
* Feat: add openapi specs for basic sdk contexts and playground reqs
* Feat: add openapi spec for response
* Feat: add openAPI entry for playground endpoint
* Fix: remove required 'projects' property that doesn't exist
* Refactor: add test placeholders for playground api
* Chore: improve openAPI description for playground request
* Refactor: align example project names
* Fix: update openapi snapshot
* Fix: summary -> description; example -> examples
* Feat: add fast-check and stub out one test.
The test doesn't work yet.
* Feat: add test and generator for sdk context schema
* Feat: add generators and tests for all new schemas
* Feat: test that the same input is returned exactly
* Feat: add more tests and more schemas
* Refactor: clean up tests some
* Refactor: simplify url friendliness check
* Refactor: fix types for playground request schema generator
* Feat: add bad request test
* Fix: make parameters the correct shape in generator
* Feat: scaffold out tests for service and endpoint
Liberal use of @ts-expect-error
* Fix: update snapshot with new model
* Add missing appName
* wip: stub out some extra tests
* Feat: model strategies for testing
* Feat: model variant payloads better
* Refactor: input params for function
* Refactor: use email address for user id generation
* Chore: update comment
* Wip: start stubbing out e2e tests
* Refactor: move tests requiring db to e2e file
* Fix: make e2e tests run as expected
* Fix: make toggle generator test work as expected
* Fix: increase timeout for long-running e2e test
* Wip: map toggles test
* Wip: test movement and cleanup
* Refactor: remove `AllowedStrings` in favor of typeof X[number]
* Wip: add e2e tests for the service
* Wip: tests in progress
* Feat: return fuller variant value
* Wip: delete redundant test.
Both those tests were testing versions of the same thing, so let's
delete one of them
* Feat: update openAPI snapshot
* Feat: hook up the playground service
* Feat: fix test cases for e2e api
* Refactor: get rid of _one_ 'as unknown as x' cast
* Fix: wait for the client to be ready before we pass it back
* Fix: weights go to 1000!
* Fix: fix some test assertions, add one more test to be sure
* Wip: add some test parameters to hopefully avoid timeouts
* Fix: don't init the client if there are no toggles
If you don't provide it with any toggles to bootstrap, then the client
will never be ready. This avoids that.
This adds two ways around it because we'll probably get away with a
bit less computation if we don't even try to initialize it. However,
we also don't want anyone else to make this mistake.
* Chore: modify test params
* Feat: use the type system to avoid empty lists for initialization
* Refactor: make tests simpler
* Feat: test basic context values
* Feat: test dynamic context values
* Fix: make custom context field test more reliable
* Feat: use unique arrays for toggles
* Feat: make `appName` required in context
* Fix: sdk context schema arbitrary: make appName at least 1 char long
* Fix: add a minimum length on appName in the context schema
* Fix: fix tests that fail due to new requirements
* Fix: update a test: remove variant mapping testing
* Fix: fix remaining tests
* Feat: rename response.toggles -> response.features
* Refactor: avoid single-letter predicate variables
* Refactor: extract offlineclient into its own file
* Refactor: move arbitraries into separate file
* Refactor: move playground requests into util function
* Fix: remove duplicate declaration of urlFriendlyString
* Chore: update comment
* Refactor: align on arbitrary generator naming
* Feat: Export single strategy arbitrary
* Refactor: move openapi utils into /util directory
* Refactor: move utils test into `util` directory
* Refactor: don't expose standard responses tied to status codes
* Feat: update empty response description + make it const
* Chore: update snapshot with new response descriptions
* refactor: add schemas to user admin controller
* refactor: remove unused SessionService
* refactor: fix search query type confusion
* refactor: add schemas to user controller (#1693)
* refactor: add schemas to user controller
* refactor: fix getAllUserSplashes method name
* refactor: name and email should not be required on create
* refactor: only some user fields may be updated
* refactor: should not require any fields on user update (#1730)
* refactor: send 400 instead of 500 on missing username and email
* refactor: should not require any fields for user update
* refactor: note that earlier versions required name or email
* refactor: merge roleDescriptionSchema and roleSchema
* fix: Does not delete api_tokens on drop-Import
* feat: Cleans unused apiTokens on environment import
* refactor: Moves ALL_PROJECTS and ALL_ENVIRONMENTS to constants
* refactor: Renames migration 20220528143630 for a more precise name
* refactor: Removes unecessary console.log
* fix: Adds correct down-script for migration 20220528143630
* fix: apply query from checkProjectsCompatibility
* fix: require equal environments when moving toggles
* refactor: clean up project service tests
* refactor: add test for project compatibility check
* refactor: improve arraysHaveSameItems name
* feat: add OpenAPI validation to a few endpoints (2)
* refactor: use package version as the OpenAPI version
* refactor: keep the existing OpenAPI page for now
* refactor: add snapshots tests for the OpenAPI output
* refactor: validate Content-Type by default
* refactor: update vulnerable deps
* refactor: fix documentation URL to match schema
* refactor: improve external type declaration
* refactor: remove unused package resolutions
* refactor: try express-openapi fork
* Update package.json
* Update src/lib/services/openapi-service.ts
* Update src/lib/types/openapi.d.ts
* Update src/lib/types/openapi.d.ts
Co-authored-by: Ivar Conradi Østhus <ivarconr@gmail.com>
This adds support for multi project tokens to be created. Backward compatibility is handled at 3 different layers here:
- The API is made backwards compatible though a permissive data type that accepts either a project?: string or projects?: string[] property, validation is done through JOI here, which ensures that projects and project are not set together. In the case of neither, this defaults to the previous default of ALL_PROJECTS
- The service layer method to handle adding tokens has been made tolerant to either of the above case and has been deprecated, a new method supporting only the new structure of using projects has been added
- Existing compatibility for consumers of Unleash as a library should not be affected either, the ApiUser constructor is now tolerant to the the first input and will internally map to the new cleaned structure
* fix: reduce project overview query count to 2.
Previously we've been doing N+1 queries for projects, this now changes to doing one query for projects with feature counts, and then one query for membercounts for all projects and merging that with the first query.
* refactor: add an hoursBack query param to the raw metrics endpoint
* refactor: explicitly return undefined
* refactor: make parseHoursBackQueryParam non-static
* refactor: add test for hoursBack query param
* refactor: improve arg name
* refactor: add a 1 hour test case
* feat: add impression data column
* fix: add default value to impressionData
* fix: allow client api to return impressionData
* fix: add tests for impressionData
* fix: reset server-dev
* fix: add test for adding a toggle with impression data on a different project
* fix: update tests
* wip: environment for permissions
* fix: add migration for roles
* fix: connect environment with access service
* feat: add tests
* chore: Implement scaffolding for new rbac
* fix: add fake store
* feat: Add api endpoints for roles and permissions list
* feat: Add ability to provide permissions when creating a role and rename environmentName to name in the list permissions datastructure
* fix: Make project roles resolve correctly against new environments permissions structure
* fix: Patch migration to also populate permission names
* fix: Make permissions actually work with new environments
* fix: Add back to get permissions working for editor role
* fix: Removed ability to set role type through api during creation - it's now always custom
* feat: Return permissions on get role endpoint
* feat: Add in support for updating roles
* fix: Get a bunch of tests working and delete a few that make no sense anymore
* chore: A few small cleanups - remove logging and restore default on dev server config
* chore: Refactor role/access stores into more logical domains
* feat: Add in validation for roles
* feat: Patch db migration to handle old stucture
* fix: migration for project roles
* fix: patch a few broken tests
* fix: add permissions to editor
* fix: update test name
* fix: update user permission mapping
* fix: create new user
* fix: update root role test
* fix: update tests
* feat: Validation now works when updating a role
* fix: Add in very barebones down migration for rbac so that tests work
* fix: Improve responses from role resolution - getting a non existant role will throw a NotFound error
* fix: remove unused permissions
* fix: add test for connecting roles and deleting project
* fix: add test for adding a project member with a custom role
* fix: add test for changing user role
* fix: add guard for deleting role if the role is in use
* fix: alter migration
* chore: Minor code cleanups
* chore: Small code cleanups
* chore: More minor cleanups of code
* chore: Trim some dead code to make the linter happy
* feat: Schema validation for roles
* fix: setup permission for variant
* fix: remove unused import
* feat: Add cascading delete for role_permissions when deleting a role
* feat: add configuration option for disabling legacy api
* chore: update frontend to beta version
* 4.6.0-beta.0
* fix: export default project constant
* fix: update snapshot
* fix: module pattern ../../lib
* fix: move DEFAULT_PROJECT to types
* fix: remove debug logging
* fix: remove debug log state
* fix: Change permission descriptions
* fix: roles should have unique name
* fix: root roles should be connected to the default project
* fix: typo in role-schema.ts
* fix: Role permission empty string for non environment type
* feat: new permission for moving project
* fix: add event for changeProject
* fix: Removing a user from a project will now check to see if that project has an owner, rather than checking if any project has an owner
* fix: add tests for move project
* fix: Add in missing create/delete tag permissions
* fix: Removed duplicate impl caused by multiple good samaritans putting it back in!
* fix: Trim out add tag permissions, for now at least
* chore: Trim out new add and delete tag permissions - we're going with update feature instead
* chore: update frontend
* 4.6.0-beta.1
* feat: Prevent editing of built in roles
* fix: Patch an issue where permissions for variants/environments didn't match the front end
* fix: lint
Co-authored-by: Ivar Conradi Østhus <ivarconr@gmail.com>
Co-authored-by: Fredrik Oseberg <fredrik.no@gmail.com>
Adds support for initializing a fresh Unleash instance with predefined API tokens.
Co-authored-by: sighphyre <liquidwicked64@gmail.com>
Co-authored-by: Juraj Malenica <juraj.malenica@mindsmiths.com>
Co-authored-by: Ivar Conradi Østhus <ivarconr@gmail.com>
* fix: Update updateUser code to reject empty emails
This fixes an issue where the updateUser call would allow null email
addresses, then update the email to null and then raise an exception,
leaving the db in a state where no user could be resolved.
* fix: remove username/email requirement in user.ts
Co-authored-by: Ivar Conradi Østhus <ivarconr@gmail.com>
This triggers when we update or overwrite variants, and will include the
previous variants and the new variants.
Co-authored-by: Ivar Østhus <ivarconr@gmail.com>
* fix: sort variants on output
We found that for existing variants, the sorting by name wasn't applied, so the index in the patches were wrong. This PR adds the sort also when we're getting variants as part of the getFeature call, not just when we're getting the variants. This should make the UX consistent, and prevent our patches from hitting the wrong index in the variants array.
Co-authored-by: Youssef Khedher <khedher.youssef@hotmail.fr>
* task: Ban changes to variants through feature
After adding the new `/variants` endpoint for features we now have a way
to access control adding/modifying variants, so the /:featureName
endpoint should no longer allow editing/adding variants.
This removes variants as a known field from the featureMetadata schema
and tells joi to stripUnknown, thus making sure we never include
variants in the initial creation or future update calls.
For the old features v1 API we allow it to declare that it has already
validated the data coming with its own schema, so we should use the data
we get from it. Thus keeping the old v1 functionality intact
Co-authored-by: Simon Hornby <simon@getunleash.ai>
- Since the archived toggles are not visible in the health dashboard,
including them in the health rating calculation makes for some really
confusing dashboards. This PR makes sure we only include non-archived
toggles when calculating health.
Add a new .../:feature/variants API
This adds
- `GET /api/admin/projects/:projectId/features/:featureName/variants` which returns
```json
{ version: '1', variants: IVariant[] }
```
- `PATCH /api/admin/projects/:projectId/features/:featureName/variants` which accepts a json patch set and updates the feature's variants field and then returns
```json
{ version: '1', variants: IVariant[] }
```
- `PUT /api/admin/projects/:projectId/features/:featureName/variants`
which accepts a IVariant[] and overwrites the current variants list for the feature defined in :featureName and returns
```json
{ version: '1', variants: IVariant[] }
- This also makes sure the total weight of all variants is == 1000
- Validates that there is at least 1 'variable' variant if there are variants
- Validates that 'fix' variants total weight can't exceed 1000
- Adds tests for all these invariants.
Co-authored-by: Simon Hornby <simon@getunleash.ai>
* fix: prevent deadlock for batchinserting usage metrics
In client metrics v2 we utilize postgres to count the usage
across a few dimentions (featureName, app_name, environment).
It turns out that if the UPDATE values are not executed in a predictable
order we can end up in a deadlock scenario with postgresql.
In this fix we thus sort the metrics on the feature_name, app_name and
envrionment, to make sure they always are executed in a predictabel
order, and thus avoiding independent inserts colliding in to a deadlock
waiting for eachother.
* fix: tests cannot assume order
- In order for a feature toggle to be allowed to change project, the
target project must have the same enabled environments.
- If the feature toggle has an environment which is not in use that does
not exist in target project, this is ok.
Co-authored-by: Fredrik Strand Oseberg <fredrik.no@gmail.com>
Co-authored-by: Fredrik Strand Oseberg <fredrik.no@gmail.com>
Adds a new way of handling usage metrics where we push it directly to the database and performs aggregation on the fly. All metrics are aggregated in to buckets of hours. We will for now store metrics for the 48 hours with the following dimensions:
- featureName
- projectName
- envrionment
- yes (the actual count)
- no (the actual count)
* feat: add new more specific feature/environment events to addons
* Updated strategy change text
* Update all three addon messages for strategy
* Link to new features view for strategy change text
Co-authored-by: Ivar Conradi Østhus <ivarconr@gmail.com>
- Adds development and production environments.
- Connects default environment to all projects
- When creating a project connects the project to all enabled
environments
Our testing and internal validation has proven that
the :global: environment concept confuses people more
than the problems it solves. We have thus decided to
group all configuration that was created before the
environment concept was introduced in to the "default
environment. This would still make everything work
as before in addition to introducing the env concept.
Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
* feat: add project and environment columns to events
* Added events for feature_strategy update
* fix duplicate test key for dbInit
* Fix argument list for toggleService calls in tests
- Adding, updating and renaming environments are meant to be
enterprise only features, as such, this PR moves these operations out
of this server
- We still keep sortOrder updating, toggling on/off and getting one,
getting all, so we can still work with environments in the OSS version
as well.
Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
This allows frontend to support a toggle for admins wanting to create
users and passwords manually, without sending emails to users they
create.
Co-authored-by: Ivar Conradi Østhus <ivarconr@gmail.com>
Adds environment support
This PR adds environments as a first-class concept in Unleash.
It necessitated a full rewrite on how we connect feature <-> strategy, as well as a rethink on which levels environments makes sense.
This enables PUTs on strategy configurations for a feature, since all strategies now have ids.
This also updates export/import format. The importer handles both formats, but export is no longer possible in version 1 of the export format, only in version 2, with strategy configurations for a feature as a separate object.
Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
Co-authored-by: Fredrik Oseberg <fredrik.no@gmail.com>
Co-authored-by: Ivar Conradi Østhus <ivarconr@gmail.com>
* feat: setup user feedback service
* fix: map rows
* feat: add tests
* wrap service calls in try catch
* fix: add test for retrieving feedback on user
* feat: add fake user feedback store
* fix: check ffor feedback id in controller
* feat: add test for bad request
* chore: expose an endpoint to really delete a toggle
- To provide a way to run end-to-end tests without cluttering
our demo instance with way too many feature-toggles, making this
endpoint available will allow end-to-end tests to clean up properly
after themselves
* chore: update changelog
* chore: update changelog
* feat: format asset paths and insert baseUri in html
* feat: add tests
* feat: pass dependencies to pre router hook
Co-authored-by: Ivar Conradi Østhus <ivarconr@gmail.com>
* feat: send email when adding a new user
* fix: rename method
* fix: create welcome email
* fix: update email templates
* fix: add name to templates
* refactor: reduce database calls to one
* fix: alter tests
* fix: remove console logs
feat: options are now typed
- This makes it easier to know what to send to unleash.start / unleash.create
- Using a Partial to instantiate the config, then melding it with defaults to get a config object with all fields set either to their defaults or to whatever is passed in.
Co-authored-by: Fredrik Strand Oseberg <fredrik.no@gmail.com>
Co-authored-by: Ivar Conradi Østhus <ivarconr@gmail.com>
feat: Add Reset token functionality
This allows admin users to create a reset token for other users. Thus allowing resetting their password.
Co-authored-by: Fredrik Oseberg <fredrik.no@gmail.com>
fixes: #778
* Make sure we keep the announced status of each app
- Since we were running onConflict().merge() we were keeping our entire
new object from our remapRow method, and that was overwriting the
current announcement status of the row back to false, unless we'd by
random chance actually set the announced property on our row to be
inserted.
* Add migration for cleaning up application-created events
-
fixes: #769
This PR Introduces first steps towards RBAC according to our specifications. Rbac will assume users to exist in the Unleash user table with a unique id. This is required to make correct mappings between users and roles.
* feat: add support for bulk operations on client apps/instance registration
-- stores client registrations for 5 seconds, then runs distinct and inserts them into db
fixes: #732
* feat: Handle database connection errors with 500
- If database goes away while unleash is running, unleash now stays
running, but all api endpoints will return 500.
- This includes our health endpoint, which allows k8s or similar
orchestrators to decide what should be done, rather than Unleash
terminating unexpectedly
This sets up the typescript compiler.
Allowing gradual migration to typescript.
Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
Co-authored-by: Ivar Conradi Østhus <ivarconr@gmail.com>
Co-authored-by: Fredrik Oseberg <fredrik.oseberg@getunleash.ai>
Co-authored-by: Clint Checkett <clintchecketts@churchofjesuschrist.org>
fixes: #676