• Stars
    star
    106
  • Rank 325,871 (Top 7 %)
  • Language
    Ruby
  • License
    MIT License
  • Created over 1 year ago
  • Updated 4 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

An alternative to Rails strong_parameters. Define structured and strongly-typed parameter schemas for your Rails controllers.

typed_params

CI Gem Version

typed_params is an alternative to Rails strong parameters for controller params, offering an intuitive DSL for defining structured and strongly-typed controller parameter schemas for Rails APIs.

This gem was extracted from Keygen and is being used in production to serve millions of API requests per day.

class UsersController < ApplicationController
  include TypedParams::Controller

  rescue_from TypedParams::InvalidParameterError, with: -> err {
    render_bad_request err.message, source: err.path.to_s
  }

  typed_params {
    param :first_name, type: :string, optional: true
    param :last_name, type: :string, optional: true
    param :email, type: :string
    param :password, type: :string
  }
  def create
    user = User.new(user_params)

    if user.save
      render_created user, location: v1_user_url(user)
    else
      render_unprocessable_resource user
    end
  end
end

Sponsored by:

Keygen

An open, source-available software licensing and distribution API.

__

Links:

Installation

Add this line to your application's Gemfile:

gem 'typed_params'

And then execute:

$ bundle

Or install it yourself as:

$ gem install typed_params

Supported Rubies

typed_params supports Ruby 3.1 and above. We encourage you to upgrade if you're on an older version. Ruby 3 provides a lot of great features, like pattern matching and a new shorthand hash syntax.

Documentation

You can find the documentation on RubyDoc.

We're working on improving the docs.

Features

  • An intuitive DSL — a breath of fresh air coming from strong parameters.
  • Define structured, strongly-typed parameter schemas for controllers.
  • Reuse schemas across controllers by defining named schemas.
  • Run validations on params, similar to active model validations.
  • Run transforms on params before they hit your controller.
  • Support formatters such as JSON:API.

Usage

typed_params can be used to define a parameter schema per-action on controllers.

To start, include the controller module:

class ApplicationController < ActionController::API
  include TypedParams::Controller

  rescue_from TypedParams::InvalidParameterError, with: -> err {
    render_bad_request err.message, source: err.path.to_s
  }
end

Parameter schemas

To define a parameter schema, you can use the .typed_params method. These parameters will be pulled from the request body. It accepts a block containing the schema definition, as well as options.

The parameters will be available inside of the controller action with the following methods:

  • #{controller_name.singularize}_params
  • typed_params
class UsersController < ApplicationController
  typed_params {
    param :user, type: :hash do
      param :first_name, type: :string, optional: true
      param :last_name, type: :string, optional: true
      param :email, type: :string
      param :password, type: :string
      param :roles, type: :array, if: :admin? do
        items type: :string
      end
    end
  }
  def create
    user = User.new(user_params)

    if user.save
      render_created user, location: v1_user_url(user)
    else
      render_unprocessable_resource user
    end
  end
end

Query schemas

To define a query schema, you can use the .typed_query method. These parameters will be pulled from the request query parameters. It accepts a block containing the schema definition.

The parameters will be available inside of the controller action with the following methods:

  • #{controller_name.singularize}_query
  • #typed_query
class PostsController < ApplicationController
  typed_query {
    param :limit, type: :integer, coerce: true, allow_nil: true, optional: true
    param :page, type: :integer, coerce: true, allow_nil: true, optional: true
  }
  def index
    posts = Post.paginate(
      post_query.fetch(:limit, 10),
      post_query.fetch(:page, 1),
    )

    render_ok posts
  end
end

Defining schemas

The easiest way to define a schema is by decorating a specific controller action, which we exemplified above. You can use .typed_params or .typed_query to decorate a controller action.

class PostsController < ApplicationController
  typed_params {
    param :author_id, type: :integer
    param :title, type: :string, length: { within: 10..80 }
    param :content, type: :string, length: { minimum: 100 }
    param :published_at, type: :time, optional: true, allow_nil: true
    param :tag_ids, type: :array, optional: true, length: { maximum: 10 } do
      items type: :integer
    end
  }
  def create
    # ...
  end
end

As an alternative to decorated schemas, you can define schemas after an action has been defined.

class PostsController < ApplicationController
  def create
    # ...
  end

  typed_params on: :create do
    param :author_id, type: :integer
    param :title, type: :string, length: { within: 10..80 }
    param :content, type: :string, length: { minimum: 100 }
    param :published_at, type: :time, optional: true, allow_nil: true
    param :tag_ids, type: :array, optional: true, length: { maximum: 10 } do
      items type: :integer
    end
  end
end

By default, all root schemas are a :hash schema. This is because both request.request_parameters and request.query_parameters are hashes. Eventually, we'd like to make that configurable, so that you could use a top-level array schema. You can create nested schemas via the :hash and :array types.

Shared schemas

If you need to share a specific schema between multiple actions, you can define a named schema.

class PostsController < ApplicationController
  typed_schema :post do
    param :author_id, type: :integer
    param :title, type: :string, length: { within: 10..80 }
    param :content, type: :string, length: { minimum: 100 }
    param :published_at, type: :time, optional: true, allow_nil: true
    param :tag_ids, type: :array, optional: true, length: { maximum: 10 } do
      items type: :integer
    end
  end

  typed_params schema: :post
  def create
    # ...
  end

  typed_params schema: :post
  def update
    # ...
  end
end

Namespaced schemas

Schemas can have an optional :namespace. This can be especially useful when defining and sharing schemas across multiple versions of an API.

class PostsController < ApplicationController
  typed_schema :post, namespace: :v1 do
    param :title, type: :string, length: { within: 10..80 }
    param :content, type: :string, length: { minimum: 100 }
    param :author_id, type: :integer
  end

  typed_params schema: %i[v1 post]
  def create
    # ...
  end

  typed_params schema: %i[v1 post]
  def update
    # ...
  end
end

Configuration

TypedParams.configure do |config|
  # Ignore nil params that are marked optional and non-nil in the schema.
  #
  # For example, given the following schema:
  #
  #   typed_params {
  #     param :optional_key, type: :string, optional: true
  #     param :required_key, type: :string
  #   }
  #
  # And the following curl request:
  #
  #   curl -X POST http://localhost:3000 -d '{"optional_key":null,"required_key":"value"}'
  #
  # Within the controller, the params would be:
  #
  #   puts typed_params # => { required_key: 'value' }
  #
  config.ignore_nil_optionals = true

  # Key transformation applied to the parameters after validation.
  #
  # One of:
  #
  #   - :underscore
  #   - :camel
  #   - :lower_camel
  #   - :dash
  #   - nil
  #
  # For example, given the following schema:
  #
  #   typed_params {
  #     param :someKey, type: :string
  #   }
  #
  # And the following curl request:
  #
  #   curl -X POST http://localhost:3000 -d '{"someKey":"value"}'
  #
  # Within the controller, the params would be:
  #
  #   puts typed_params # => { some_key: 'value' }
  #
  config.key_transform = :underscore

  # Path transformation applied to error paths e.g. UnpermittedParameterError.
  #
  # One of:
  #
  #   - :underscore
  #   - :camel
  #   - :lower_camel
  #   - :dash
  #   - nil
  #
  # For example, given the following schema:
  #
  #   typed_params {
  #     param :parent_key, type: :hash do
  #       param :child_key, type: :string
  #     end
  #   }
  #
  # With an invalid `child_key`, the path would be:
  #
  #   rescue_from TypedParams::UnpermittedParameterError, with: -> err {
  #     puts err.path.to_s # => parentKey.childKey
  #   }
  #
  config.path_transform = :lower_camel
end

Invalid parameters

When a parameter is provided, but it fails validation (e.g. a type mismatch), a TypedParams::InvalidParameterError error will be raised.

You can rescue this error at the controller-level like so:

class ApplicationController < ActionController::API
  rescue_from TypedParams::InvalidParameterError, with: -> err {
    render_bad_request "invalid parameter: #{err.message}", parameter: err.path.to_dot_notation
  }
end

The TypedParams::InvalidParameterError error object has the following attributes:

  • #message - the error message, e.g. type mismatch (received string expected integer).
  • #path - a Path object with a pointer to the invalid parameter.
  • #source - either :params or :query, depending on where the invalid parameter came from (i.e. request body vs query parameters, respectively).

Unpermitted parameters

By default, .typed_params is :strict. This means that if any unpermitted parameters are provided, a TypedParams::UnpermittedParameterError will be raised.

For .typed_query, the default is non-strict. This means that any unpermitted parameters will be ignored.

You can rescue this error at the controller-level like so:

class ApplicationController < ActionController::API
  # NOTE: Should be rescued before TypedParams::InvalidParameterError
  rescue_from TypedParams::UnpermittedParameterError, with: -> err {
    render_bad_request "unpermitted parameter: #{err.path.to_jsonapi_pointer}"
  }
end

The TypedParams::UnpermittedParameterError error object has the following attributes:

  • #message - the error message, e.g. unpermitted parameter.
  • #path - a Path object with a pointer to the unpermitted parameter.
  • #source - either :params or :query, depending on where the unpermitted parameter came from (i.e. request body vs query parameters, respectively).

It inherits from TypedParams::InvalidParameterError.

Parameter options

Parameters can have validations, transforms, and more.

Parameter key

The parameter's key.

param :foo

This is required.

Parameter type

The parameter's type. Please see Types for more information. Some types may accept a block, e.g. :hash and :array.

param :email, type: :string

This is required.

Strict parameter

When true, a TypedParams::UnpermittedParameterError error is raised for unpermitted parameters. When false, unpermitted parameters are ignored.

param :user, type: :hash, strict: true do
  # ...
end

By default, the entire .typed_params schema is strict, and .typed_query is not.

Optional parameter

The parameter is optional. An invalid parameter error will not be raised in its absence.

param :first_name, type: :string, optional: true

By default, parameters are required.

Conditional parameter

You can define conditional parameters using :if and :unless. The parameter will only be evaluated when the condition to true.

param :role, type: :string, if: -> { admin? }
param :role, type: :string, if: :admin?
param :role, type: :string, unless: -> { guest? }
param :role, type: :string, unless: :guest?

The lambda will be evaled within the current controller context.

Rename parameter

Apply a transformation that renames the parameter.

param :user, type: :integer, as: :user_id

typed_params # => { user_id: 1 }

In this example, the parameter would be accepted as :user, but renamed to :user_id for use inside of the controller.

Alias parameter

Allow a parameter to be provided via an alias.

param :owner_id, type: :integer, alias: :user_id

In this example, the parameter would be accepted as both :owner_id and :user_id, but accessible as :owner_id inside the controller.

Noop parameter

The parameter is accepted but immediately thrown out.

param :foo, type: :string, noop: true

By default, this is false.

Coerce parameter

The parameter will be coerced if its type is coercible and the parameter has a type mismatch. The coercion can fail, e.g. :integer to :hash, and if it does, a TypedParams::InvalidParameterError will be raised.

param :age, type: :integer, coerce: true

The default is false.

Allow blank

The parameter can be #blank?.

param :title, type: :string, allow_blank: true

By default, blank params are rejected with a TypedParams::InvalidParameterError error.

Allow nil

The parameter can be #nil?.

param :tag, type: :string, allow_nil: true

By default, nil params are rejected with a TypedParams::InvalidParameterError error.

Allow non-scalars

Only applicable to the :hash type and its subtypes. Allow non-scalar values in a :hash parameter. Scalar types can be found under Types.

param :metadata, type: :hash, allow_non_scalars: true

By default, non-scalar parameters are rejected with a TypedParams::InvalidParameterError error.

Nilify blanks

Automatically convert #blank? values to nil.

param :phone_number, type: :string, nilify_blanks: true

By default, this is disabled.

Inclusion validation

The parameter must be included in the array or range.

param :log_level, type: :string, inclusion: { in: %w[DEBUG INFO WARN ERROR FATAL] }
param :priority, type: :integer, inclusion: { in: 0..9 }

Exclusion validation

The parameter must be excluded from the array or range.

param :custom_log_level, type: :string, exclusion: { in: %w[DEBUG INFO WARN ERROR FATAL] }
param :custom_priority, type: :integer, exclusion: { in: 0..9 }

Format validation

The parameter must be a certain regular expression format.

param :first_name, type: :string, format: { with: /foo/ }
param :last_name, type: :string, format: { without: /bar/ }

Length validation

The parameter must be a certain length.

param :content, type: :string, length: { minimum: 100 }
param :title, type: :string, length: { maximum: 10 }
param :tweet, type: :string, length: { within: ..160 }
param :odd, type: :string, length: { in: [2, 4, 6, 8] }
param :ten, type: :string, length: { is: 10 }

Transform parameter

Transform the parameter using a lambda. This is commonly used to transform a parameter into a nested attributes hash or array.

param :role, type: :string, transform: -> _, name {
  [:role_attributes, { name: }]
}

The lambda must accept a key (the current parameter key), and a value (the current parameter value).

The lambda must return a tuple with the new key and value.

Validate parameter

Define a custom validation for the parameter, outside of the default validations. The can be useful for defining mutually exclusive params, or even validating that an ID exists before proceeding.

# Mutually exclusive params (i.e. either-or, not both)
param :login, type: :hash, validate: -> v { v.key?(:username) ^ v.key?(:email) } do
  param :username, type: :string, optional: true
  param :email, type: :string, optional: true
  param :password, type: :string
end

# Assert user exists
param :user, type: :integer, validate: -> id {
  User.exists?(id)
}

The lambda should accept a value and return a boolean. When the boolean evaluates to false, a TypedParams::InvalidParameterError will be raised.

To customize the error message, the lambda can raise a TypedParams::ValidationError error:

param :invalid, type: :string, validate: -> v {
  raise TypedParams::ValidationError, 'is always invalid'
}

Polymorphic parameter

Note: currently, this option is only utilized by the JSONAPI formatter.

Define a polymorphic parameter. Actual behavior will vary based on the formatter being used.

format :jsonapi

param :data, type: :hash do
  param :relationships, type: :hash do
    param :owner, type: :hash, polymorphic: true do
      param :data, type: :hash do
        param :type, type: :string, inclusion: { in: %w[users user] }
        param :id, type: :integer
      end
    end
  end
end

typed_params # => { owner_type: 'User', owner_id: 1 }

In this example, a polymorphic :owner relationship is defined. When run through the JSONAPI formatter, instead of formatting the relationship into solely the :owner_id key, it also includes the :owner_type key for a polymorphic association.

Shared options

You can define a set of options that will be applied to immediate children parameters (i.e. not grandchilden).

with if: :admin? do
  param :referrer, type: :string, optional: true
  param :role, type: :string
end

Scalar types

String type

Type :string. Defines a string parameter. Must be a String.

Boolean type

Type :boolean. Defines a boolean parameter. Must be TrueClass or FalseClass.

Integer type

Type :integer. Defines an integer parameter. Must be an Integer.

Float type

Type :float. Defines a float parameter. Must be a Float.

Decimal type

Type :decimal. Defines a decimal parameter. Must be a BigDecimal.

Number type

Type :number. Defines a number parameter. Must be either an Integer, a Float, or a BigDecimal.

Symbol type

Type :symbol. Defines a symbol parameter. Must be a Symbol.

Time type

Type :time. Defines a time parameter. Must be a Time.

Date type

Type :date. Defines a date parameter. Must be a Date.

Non-scalar types

Array type

Type :array. Defines an array parameter. Must be an Array.

Arrays are a special type. They can accept a block that defines its item types, which may be a nested schema.

# array of hashes
param :endless_array, type: :array do
  items type: :hash do
    # ...
  end
end
# array of 1 integer and 1 string
param :bounded_array, type: :array do
  item type: :integer
  item type: :string
end

Hash type

Type :hash. Defines a hash parameter. Must be a Hash.

Hashes are a special type. They can accept a block that defines a nested schema.

# define a nested schema
param :parent, type: :hash do
  param :child, type: :hash do
    # ...
  end
end

# non-schema hash
param :only_scalars, type: :hash
param :non_scalars_too, type: :hash, allow_non_scalars: true

Custom types

You may register custom types that can be utilized in your schemas.

Each type consists of, at minimum, a match: lambda. For more usage examples, see the default types.

TypedParams.types.register(:metadata,
  archetype: :hash,
  match: -> value {
    return false unless
      value.is_a?(Hash)

    # Metadata can have one layer of nested arrays/hashes
    value.values.all? { |v|
      case v
      when Hash
        v.values.none? { _1.is_a?(Array) || _1.is_a?(Hash) }
      when Array
        v.none? { _1.is_a?(Array) || _1.is_a?(Hash) }
      else
        true
      end
    }
  },
)

Formats

Out of the box, typed_params ships with two formatters. Formatters are run after all validations and transforms, formatting the params from one format to another format.

By default, no formatter is used.

JSONAPI format

You can add convenient support for JSONAPI by using the :jsonapi format.

All request data will be transformed into a hash, useable within models.

In addition, request meta will be available inside of the controller action with the following methods:

  • #{controller_name.singularize}_meta
  • #typed_meta
class UsersController < ApplicationController
  typed_params {
    format :jsonapi

    param :data, type: :hash do
      param :type, type: :string, inclusion: { in: %w[users user] }, noop: true
      param :id, type: :string, noop: true
      param :attributes, type: :hash do
        param :first_name, type: :string, optional: true
        param :last_name, type: :string, optional: true
        param :email, type: :string, format: { with: /@/ }
        param :password, type: :string
      end
      param :relationships, type: :hash do
        param :team, type: :hash do
          param :data, type: :hash do
            param :type, type: :string, inclusion: { in: %w[teams team] }
            param :id, type: :string
          end
        end
      end
    end

    param :meta, type: :hash, optional: true do
      param :affilate_id, type: :string, optional: true
    end
  }
  def create
    puts user_params
    # => {
    #      first_name: 'John',
    #      last_name: 'Smith',
    #      email: '[email protected]',
    #      password: '7c84241a1102',
    #      team_id: '1',
    #    }

    puts user_meta
    # => { affilate_id: 'e805' }
  end
end

Rails format

You can add conventional wrapped params using the :rails format.

class UsersController < ApplicationController
  typed_params {
    format :rails

    param :first_name, type: :string, optional: true
    param :last_name, type: :string, optional: true
    param :email, type: :string, format: { with: /@/ }
    param :password, type: :string
    param :team_id, type: :string
  }
  def create
    puts user_params
    # => {
    #      user: {
    #        first_name: 'John',
    #        last_name: 'Smith',
    #        email: '[email protected]',
    #        password: '7c84241a1102',
    #        team_id: '1',
    #      }
    #    }
  end
end

Is it any good?

Yes.

Contributing

If you have an idea, or have discovered a bug, please open an issue or create a pull request.

For security issues, please see SECURITY.md

License

The gem is available as open source under the terms of the MIT License.

More Repositories

1

keygen-api

Keygen is a fair source software licensing and distribution API built with Ruby on Rails. For developers, by developers.
Gherkin
752
star
2

request_migrations

Write request and response migrations for Stripe-like versioning of your Ruby on Rails API. Make breaking changes without breaking things!
Ruby
105
star
3

keygen-go

Keygen reference SDK for Go. Integrate license activation, automatic updates and offline licensing for Go binaries.
Go
98
star
4

example-electron-license-activation

An example of how to implement software licensing and device activation in an Electron application
JavaScript
91
star
5

py-machineid

Get the unique machine ID of any host (without admin privileges).
Python
53
star
6

example-paddle-integration

An example Node.js app that integrates Keygen with Paddle for accepting payments.
JavaScript
33
star
7

example-electron-app

An example Electron app that uses Keygen for licensing and auto-updates.
JavaScript
33
star
8

air-gapped-activation-example

An example implementation of offline activation for air-gapped machines using QR codes, signed and encrypted license files, and a mobile device.
TypeScript
32
star
9

example-wordpress-plugin

An example WordPress plugin that uses Keygen for site-locked licensing.
PHP
24
star
10

example-stripe-integration

An example Node.js app that integrates Keygen with Stripe for accepting payments.
JavaScript
23
star
11

example-node-activation-server

An example Node server that performs license creation, activation and validation using Keygen.
JavaScript
21
star
12

example-python-machine-activation

An example implementation of a node-locked license activation flow using Keygen and Python
Python
19
star
13

basic-example-electron-app

A simplistic Electron app example that uses Keygen for license key validation.
HTML
19
star
14

keygen-cli

Official command line tool for publishing releases to Keygen's distribution API.
Go
18
star
15

example-electron-license-gate

An example of adding a license gate to an Electron app, requiring a valid license to "unlock" the main application window.
JavaScript
18
star
16

example-php-activation-server

An example PHP server that performs license creation, activation and validation using Keygen.
PHP
17
star
17

example-go-program

A self-updating Go program that uses Keygen for licensing and auto-updates.
Go
13
star
18

keygen-zapier

An official Zapier integration for Keygen.
TypeScript
12
star
19

keygen-relay

An offline-first on-premise licensing server backed by Keygen.
Go
11
star
20

example-python-cryptographic-verification

Example of verifying a license key's authenticity using Ed25519 and RSA-SHA256 with various padding schemes
Python
11
star
21

community

Join the Keygen community. Ask questions, talk about software development, discuss licensing, and show off your work!
9
star
22

example-gumroad-integration

An example Node.js app that integrates Keygen with Gumroad for accepting payments.
JavaScript
9
star
23

example-rust-license-validation

An example of making a simple license validation request from a Rust command line program
Rust
9
star
24

example-python-offline-validation-caching

An example of utilizing license validation caching and cryptographic verification for offline use
Python
9
star
25

example-python-machine-heartbeats

Example of node-locked machine activation with a heartbeat monitor.
Python
8
star
26

example-cpp-cryptographic-verification

Example of verifying a license key's authenticity using RSA-SHA256 with PKCS1 v1.5 padding
C++
8
star
27

example-rust-cryptographic-license-files

Example of verifying cryptographically signed and encrypted license files using Rust, Ed25519 and AES-256-GCM
Rust
7
star
28

example-cpp-gui-license-validation

An example of making a simple license validation request from a Qt/C++ GUI program
C++
6
star
29

example-cpp-cryptographic-license-files

Example of verifying cryptographically signed and encrypted license files using C++, OpenSSL, Ed25519 and AES-256-GCM.
C
6
star
30

example-python-cryptographic-machine-files

Example of verifying cryptographically signed and encrypted machine files using Python, Ed25519 and AES-256-GCM.
Python
6
star
31

example-csharp-cryptographic-license-files

Example of verifying cryptographically signed and encrypted license files using C#, NSec, Bouncy Castle, Ed25519 and AES-256-GCM.
C#
6
star
32

example-node-machine-activation

An example implementation of a typical machine activation flow using Keygen
JavaScript
6
star
33

example-fastspring-integration

An example Node.js app that integrates Keygen with FastSpring for accepting payments.
JavaScript
6
star
34

example-csharp-cryptographic-verification

Example of verifying cryptographically signed license keys using C#, Bouncy Castle and RSA PSS-SHA256
C#
6
star
35

example-csharp-license-activation

An example implementation of a node-locked license activation flow using Keygen and C# .NET
C#
5
star
36

example-react-licensing-portal

An example customer-facing licensing portal built using Keygen's API and React
JavaScript
5
star
37

example-cpp-license-validation

An example of making a simple license validation request from a C++ command line program
C++
5
star
38

example-embedded-license-key-data

An example implementation of embedding data inside of cryptographically signed license keys using RSA cryptography, for use in offline licensing models.
JavaScript
5
star
39

example-private-npm-package

An example of publishing a private Node package to a private npm registry hosted by Keygen
JavaScript
5
star
40

example-dart-cryptographic-license-files

Example of verifying cryptographically signed and encrypted license files using Dart, Ed25519 and AES-256-GCM
Dart
5
star
41

example-cpp-user-authentication

Example of authenticating as a user and interacting with Keygen's API
C++
5
star
42

example-react-license-validation

An example implementation of validating a license key from within a React component.
JavaScript
4
star
43

example-sendowl-integration

An example Node.js app that integrates Keygen with SendOwl for accepting payments.
JavaScript
4
star
44

example-node-response-signature-verification

An example implementation of verifying response signatures using cryptography to prevent tampering with cache payloads, replay attacks and MITM attacks.
JavaScript
4
star
45

example-csharp-license-validation

An example of making a simple license validation request from a C# .NET console application
C#
4
star
46

example-csharp-user-authentication

An example implementation of user authentication using Keygen and C# .NET
C#
4
star
47

example-cryptographic-verification

An example implementation of cryptographically verifying license key authenticity using ECC and RSA cryptography, for use in offline licensing models.
JavaScript
4
star
48

example-cpp-response-signature-verification

Example of verifying response signatures using portable Ed25519
C
4
star
49

example-csharp-validation-caching

An example of license validation caching for a C# .NET 5 console application
C#
3
star
50

example-multi-tenant-licensing-server

An example of how to implement a multi-tenant node-locked licensing server.
JavaScript
3
star
51

example-csharp-hybrid-online-offline-licensing

An example of implementing a hybrid online/offline licensing system using Keygen
C#
3
star
52

example-validation-caching

An example command line script that caches validation responses to the filesystem for offline licensing.
JavaScript
3
star
53

example-bash-license-activation

Example of secure license key activation in a Bash script.
Shell
3
star
54

example-go-license-validation

An example of making a simple license validation request from a Go command line program
Go
2
star
55

example-duplicate-machine-suspension-job

An example job which suspends licenses based on duplicate machine instances
Python
2
star
56

example-python-release-upload

Example of using Python to create a new release and upload a release artifact.
Python
2
star
57

example-python-activation-proof-verification

Example of verifying signed machine activation proofs using RSA PKCS1 v1.5 padding with a SHA256 digest.
Python
2
star
58

example-bash-cryptographic-verification

Example of verifying a license key's authenticity using RSA-SHA256 with PKCS1 PSS padding with Bash.
Shell
2
star
59

example-java-cryptographic-license-files

Example of verifying cryptographically signed and encrypted license files using Java, Bouncy Castle, Ed25519 and AES-256-GCM
Java
2
star
60

example-java-cryptographic-license-keys

Example of verifying cryptographically signed license keys using Java, Bouncy Castle and Ed25519
Java
2
star
61

fcl.dev

The website for the Fair Core License. Fair Core is to Fair Source what Open Core is to Open Source.
HTML
2
star
62

example-webhook-handler

An example Node.js app that handles webhook events from Keygen
JavaScript
1
star
63

example-password-reset-fulfillment

An example of fulfilling password reset requests with your own domain and email provider
JavaScript
1
star
64

example-csv-importer

An example script that imports a collection of users into Keygen from a CSV dataset
JavaScript
1
star
65

example-node-cryptographic-license-files

Example of verifying cryptographically signed and encrypted license files using Node, Ed25519 and AES-256-GCM.
JavaScript
1
star
66

example-moonclerk-integration

An example Node.js app that integrates Keygen with MoonClerk for accepting payments.
JavaScript
1
star
67

example-python-bulk-machine-deactivation

An example of deactivating a license's machines in bulk using Keygen's API
Python
1
star
68

example-dist-proxy

An example Node.js app that proxies release downloads from Keygen Dist.
JavaScript
1
star