mirror of
https://github.com/zitadel/zitadel.git
synced 2025-02-28 21:47:23 +00:00
feat(actions): add "zitadel/uuid" module (#6135)
* feat: add "zitadel/uuid" module * feat(actions/uuid): add v1, v3, and v4 UUIDs * add namespaces and improve hash based functions * add docs --------- Co-authored-by: Florian Forster <florian@zitadel.com> Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
parent
831a21a6e2
commit
5a9609ef29
@ -51,3 +51,58 @@ The object has the following fields and methods:
|
|||||||
Returns the body as JSON object, or throws an error if the body is not a json object.
|
Returns the body as JSON object, or throws an error if the body is not a json object.
|
||||||
- `text()` *string*
|
- `text()` *string*
|
||||||
Returns the body
|
Returns the body
|
||||||
|
|
||||||
|
## UUID
|
||||||
|
|
||||||
|
This module provides functionality to generate a UUID
|
||||||
|
|
||||||
|
### Import
|
||||||
|
|
||||||
|
```js
|
||||||
|
let uuid = require("zitadel/uuid")
|
||||||
|
```
|
||||||
|
|
||||||
|
### `uuid.vX()` function
|
||||||
|
|
||||||
|
This function generates a UUID using [google/uuid](https://github.com/google/uuid). `vX` allows to define the UUID version:
|
||||||
|
|
||||||
|
- `uuid.v1()` *string*
|
||||||
|
Generates a UUID version 1, based on date-time and MAC address
|
||||||
|
- `uuid.v3(namespace, data)` *string*
|
||||||
|
Generates a UUID version 3, based on the provided namespace using MD5
|
||||||
|
- `uuid.v4()` *string*
|
||||||
|
Generates a UUID version 4, which is randomly generated
|
||||||
|
- `uuid.v5(namespace, data)` *string*
|
||||||
|
Generates a UUID version 5, based on the provided namespace using SHA1
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- `namespace` *UUID*/*string*
|
||||||
|
Namespace to be used in the hashing function. Either provide one of defined [namespaces](#namespaces) or a string representing a UUID.
|
||||||
|
- `data` *[]byte*/*string*
|
||||||
|
data to be used in the hashing function. Possible types are []byte or string.
|
||||||
|
|
||||||
|
### Namespaces
|
||||||
|
|
||||||
|
The following predefined namespaces can be used for `uuid.v3` and `uuid.v5`:
|
||||||
|
|
||||||
|
- `uuid.namespaceDNS` *UUID*
|
||||||
|
6ba7b810-9dad-11d1-80b4-00c04fd430c8
|
||||||
|
- `uuid.namespaceURL` *UUID*
|
||||||
|
6ba7b811-9dad-11d1-80b4-00c04fd430c8
|
||||||
|
- `uuid.namespaceOID` *UUID*
|
||||||
|
6ba7b812-9dad-11d1-80b4-00c04fd430c8
|
||||||
|
- `uuid.namespaceX500` *UUID*
|
||||||
|
6ba7b814-9dad-11d1-80b4-00c04fd430c8
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```js
|
||||||
|
let uuid = require("zitadel/uuid")
|
||||||
|
function setUUID(ctx, api) {
|
||||||
|
if (api.metadata === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
api.v1.user.appendMetadata('custom-id', uuid.v4());
|
||||||
|
}
|
||||||
|
```
|
83
internal/actions/uuid_module.go
Normal file
83
internal/actions/uuid_module.go
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package actions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/dop251/goja"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/zitadel/logging"
|
||||||
|
)
|
||||||
|
|
||||||
|
func WithUUID(ctx context.Context) Option {
|
||||||
|
return func(c *runConfig) {
|
||||||
|
c.modules["zitadel/uuid"] = func(runtime *goja.Runtime, module *goja.Object) {
|
||||||
|
requireUUID(ctx, runtime, module)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func requireUUID(_ context.Context, runtime *goja.Runtime, module *goja.Object) {
|
||||||
|
o := module.Get("exports").(*goja.Object)
|
||||||
|
logging.OnError(o.Set("v1", inRuntime(uuid.NewUUID, runtime))).Warn("unable to set module")
|
||||||
|
logging.OnError(o.Set("v3", inRuntimeHash(uuid.NewMD5, runtime))).Warn("unable to set module")
|
||||||
|
logging.OnError(o.Set("v4", inRuntime(uuid.NewRandom, runtime))).Warn("unable to set module")
|
||||||
|
logging.OnError(o.Set("v5", inRuntimeHash(uuid.NewSHA1, runtime))).Warn("unable to set module")
|
||||||
|
logging.OnError(o.Set("namespaceDNS", uuid.NameSpaceDNS)).Warn("unable to set namespace")
|
||||||
|
logging.OnError(o.Set("namespaceURL", uuid.NameSpaceURL)).Warn("unable to set namespace")
|
||||||
|
logging.OnError(o.Set("namespaceOID", uuid.NameSpaceOID)).Warn("unable to set namespace")
|
||||||
|
logging.OnError(o.Set("namespaceX500", uuid.NameSpaceX500)).Warn("unable to set namespace")
|
||||||
|
}
|
||||||
|
|
||||||
|
func inRuntime(function func() (uuid.UUID, error), runtime *goja.Runtime) func(call goja.FunctionCall) goja.Value {
|
||||||
|
return func(call goja.FunctionCall) goja.Value {
|
||||||
|
if len(call.Arguments) != 0 {
|
||||||
|
panic("invalid arg count")
|
||||||
|
}
|
||||||
|
|
||||||
|
uuid, err := function()
|
||||||
|
if err != nil {
|
||||||
|
logging.WithError(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return runtime.ToValue(uuid.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func inRuntimeHash(function func(uuid.UUID, []byte) uuid.UUID, runtime *goja.Runtime) func(call goja.FunctionCall) goja.Value {
|
||||||
|
return func(call goja.FunctionCall) goja.Value {
|
||||||
|
if len(call.Arguments) != 2 {
|
||||||
|
logging.WithFields("count", len(call.Arguments)).Debug("other than 2 args provided")
|
||||||
|
panic("invalid arg count")
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
var namespace uuid.UUID
|
||||||
|
switch n := call.Arguments[0].Export().(type) {
|
||||||
|
case string:
|
||||||
|
namespace, err = uuid.Parse(n)
|
||||||
|
if err != nil {
|
||||||
|
logging.WithError(err).Debug("namespace failed parsing as UUID")
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
case uuid.UUID:
|
||||||
|
namespace = n
|
||||||
|
default:
|
||||||
|
logging.WithError(err).Debug("invalid type for namespace")
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var data []byte
|
||||||
|
switch d := call.Arguments[1].Export().(type) {
|
||||||
|
case string:
|
||||||
|
data = []byte(d)
|
||||||
|
case []byte:
|
||||||
|
data = d
|
||||||
|
default:
|
||||||
|
logging.WithError(err).Debug("invalid type for data")
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return runtime.ToValue(function(namespace, data).String())
|
||||||
|
}
|
||||||
|
}
|
@ -564,7 +564,7 @@ func (o *OPStorage) userinfoFlows(ctx context.Context, user *query.User, userGra
|
|||||||
apiFields,
|
apiFields,
|
||||||
action.Script,
|
action.Script,
|
||||||
action.Name,
|
action.Name,
|
||||||
append(actions.ActionToOptions(action), actions.WithHTTP(actionCtx))...,
|
append(actions.ActionToOptions(action), actions.WithHTTP(actionCtx), actions.WithUUID(actionCtx))...,
|
||||||
)
|
)
|
||||||
cancel()
|
cancel()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -745,7 +745,7 @@ func (o *OPStorage) privateClaimsFlows(ctx context.Context, userID string, userG
|
|||||||
apiFields,
|
apiFields,
|
||||||
action.Script,
|
action.Script,
|
||||||
action.Name,
|
action.Name,
|
||||||
append(actions.ActionToOptions(action), actions.WithHTTP(actionCtx))...,
|
append(actions.ActionToOptions(action), actions.WithHTTP(actionCtx), actions.WithUUID(actionCtx))...,
|
||||||
)
|
)
|
||||||
cancel()
|
cancel()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -133,7 +133,7 @@ func (l *Login) runPostExternalAuthenticationActions(
|
|||||||
apiFields,
|
apiFields,
|
||||||
a.Script,
|
a.Script,
|
||||||
a.Name,
|
a.Name,
|
||||||
append(actions.ActionToOptions(a), actions.WithHTTP(actionCtx))...,
|
append(actions.ActionToOptions(a), actions.WithHTTP(actionCtx), actions.WithUUID(actionCtx))...,
|
||||||
)
|
)
|
||||||
cancel()
|
cancel()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -206,7 +206,7 @@ func (l *Login) runPostInternalAuthenticationActions(
|
|||||||
apiFields,
|
apiFields,
|
||||||
a.Script,
|
a.Script,
|
||||||
a.Name,
|
a.Name,
|
||||||
append(actions.ActionToOptions(a), actions.WithHTTP(actionCtx))...,
|
append(actions.ActionToOptions(a), actions.WithHTTP(actionCtx), actions.WithUUID(actionCtx))...,
|
||||||
)
|
)
|
||||||
cancel()
|
cancel()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -307,7 +307,7 @@ func (l *Login) runPreCreationActions(
|
|||||||
apiFields,
|
apiFields,
|
||||||
a.Script,
|
a.Script,
|
||||||
a.Name,
|
a.Name,
|
||||||
append(actions.ActionToOptions(a), actions.WithHTTP(actionCtx))...,
|
append(actions.ActionToOptions(a), actions.WithHTTP(actionCtx), actions.WithUUID(actionCtx))...,
|
||||||
)
|
)
|
||||||
cancel()
|
cancel()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -365,7 +365,7 @@ func (l *Login) runPostCreationActions(
|
|||||||
apiFields,
|
apiFields,
|
||||||
a.Script,
|
a.Script,
|
||||||
a.Name,
|
a.Name,
|
||||||
append(actions.ActionToOptions(a), actions.WithHTTP(actionCtx))...,
|
append(actions.ActionToOptions(a), actions.WithHTTP(actionCtx), actions.WithUUID(actionCtx))...,
|
||||||
)
|
)
|
||||||
cancel()
|
cancel()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user