mirror of
https://github.com/zitadel/zitadel.git
synced 2025-11-14 22:33:17 +00:00
Merge branch 'main' into mpa_contributing_20220530
This commit is contained in:
25
README.md
25
README.md
@@ -1,14 +1,3 @@
|
||||
<p align="right">
|
||||
<img src="./docs/static/img/github-header01-dark@2x.png#gh-dark-mode-only" alt="ZITADEL Cloud launched" max-height="200px" width="auto" />
|
||||
<img src="./docs/static/img/github-header01-light@2x.png#gh-light-mode-only" alt="ZITADEL Cloud launched" max-height="200px" width="auto" />
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
We are live on <a href="https://www.producthunt.com/posts/zitadel">ProductHunt</a>. <br> Thank you for the support and feedback.
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
<p align="center">
|
||||
<img src="./docs/static/logos/zitadel-logo-dark@2x.png#gh-light-mode-only" alt="Zitadel Logo" max-height="200px" width="auto" />
|
||||
<img src="./docs/static/logos/zitadel-logo-light@2x.png#gh-dark-mode-only" alt="Zitadel Logo" max-height="200px" width="auto" />
|
||||
@@ -48,16 +37,15 @@ With ZITADEL you rely on a battle tested, hardened and extensible turnkey soluti
|
||||
|
||||
---
|
||||
|
||||
**[🏡 Website](https://zitadel.com) [💬 Chat](https://zitadel.com/chat) [📋 Docs](https://docs.zitadel.ch/) [🧑💻 Blog](https://zitadel.com/blog) [📞 Contact](https://zitadel.com/contact/)**
|
||||
**[🏡 Website](https://zitadel.com) [💬 Chat](https://zitadel.com/chat) [📋 Docs](https://docs.zitadel.com/) [🧑💻 Blog](https://zitadel.com/blog) [📞 Contact](https://zitadel.com/contact/)**
|
||||
|
||||
## Get started
|
||||
|
||||
### ZITADEL Cloud (SaaS)
|
||||
|
||||
The easiest way to get started with ZITADEL is to use our public cloud offering.
|
||||
Currently ZITADEL V2 Beta is available, head over to [https://zitadel.cloud](https://zitadel.cloud) and create your first ZITADEL instance for free.
|
||||
The easiest way to get started with [ZITADEL Cloud](https://zitadel.cloud).
|
||||
|
||||
You can also discover our pay-as-you-go [pricing](https://zitadel.com/pricing).
|
||||
It's free for up to 25'000 authenticated requests. Learn more about the [pay-as-you-go pricing](https://zitadel.com/pricing).
|
||||
|
||||
### Install ZITADEL
|
||||
|
||||
@@ -65,8 +53,7 @@ You can also discover our pay-as-you-go [pricing](https://zitadel.com/pricing).
|
||||
|
||||
### Quickstarts - Integrate your app
|
||||
|
||||
- [Multiple Quickstarts can be found here](https://docs.zitadel.com/docs/guides/start/quickstart)
|
||||
- [And even more examples are located under zitadel/zitadel-examples](https://github.com/zitadel/zitadel-examples)
|
||||
[Multiple Examples can be found here](https://docs.zitadel.com/docs/examples/introduction)
|
||||
|
||||
> If you miss something please feel free to [join the Discussion](https://github.com/zitadel/zitadel/discussions/1717)
|
||||
|
||||
@@ -74,7 +61,7 @@ You can also discover our pay-as-you-go [pricing](https://zitadel.com/pricing).
|
||||
|
||||
- [API-first](https://docs.zitadel.com/docs/apis/introduction)
|
||||
- Strong audit trail thanks to [event sourcing](https://docs.zitadel.com/docs/concepts/eventstore/overview)
|
||||
- [Actions](https://docs.zitadel.ch/docs/concepts/features/actions) to react on events with custom code
|
||||
- [Actions](https://docs.zitadel.com/docs/concepts/features/actions) to react on events with custom code
|
||||
- [Branding](https://docs.zitadel.com/docs/guides/manage/customize/branding) for a uniform user experience
|
||||
- [CockroachDB](https://www.cockroachlabs.com/) is the only dependency
|
||||
|
||||
@@ -96,6 +83,8 @@ You can also discover our pay-as-you-go [pricing](https://zitadel.com/pricing).
|
||||
- 🚧 [SAML 2.0](https://github.com/zitadel/zitadel/pull/3618)
|
||||
- 🚧 [Postgres](https://github.com/zitadel/zitadel/pull/3998)
|
||||
|
||||
Track upcoming features on our [roadmap](https://zitadel.com/roadmap).
|
||||
|
||||
## Client libraries
|
||||
|
||||
<!-- TODO: check other libraries -->
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
title: ZITADEL Cloud Rate Limits
|
||||
---
|
||||
|
||||
Rate limits are implemented according to our [rate limit policy](/docs/legal/rate-limit-policy.md) with the following rules:
|
||||
|
||||
| Path | Description | Throttling | One Minute Banning |
|
||||
|--------------------------|----------------------------------------|--------------------------------------|----------------------------------------|
|
||||
| /ui/login* | Global Login, Register and Reset Limit | 10 requests per second over a minute | 15 requests per sencond over 3 minutes |
|
||||
|
||||
@@ -33,7 +33,7 @@ func (c *Commands) addUserGrant(ctx context.Context, userGrant *domain.UserGrant
|
||||
if !userGrant.IsValid() {
|
||||
return nil, nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-4M0fs", "Errors.UserGrant.Invalid")
|
||||
}
|
||||
err = c.checkUserGrantPreCondition(ctx, userGrant)
|
||||
err = c.checkUserGrantPreCondition(ctx, userGrant, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -91,7 +91,7 @@ func (c *Commands) changeUserGrant(ctx context.Context, userGrant *domain.UserGr
|
||||
}
|
||||
userGrant.ProjectID = existingUserGrant.ProjectID
|
||||
userGrant.ProjectGrantID = existingUserGrant.ProjectGrantID
|
||||
err = c.checkUserGrantPreCondition(ctx, userGrant)
|
||||
err = c.checkUserGrantPreCondition(ctx, userGrant, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -285,8 +285,8 @@ func (c *Commands) userGrantWriteModelByID(ctx context.Context, userGrantID, res
|
||||
return writeModel, nil
|
||||
}
|
||||
|
||||
func (c *Commands) checkUserGrantPreCondition(ctx context.Context, usergrant *domain.UserGrant) error {
|
||||
preConditions := NewUserGrantPreConditionReadModel(usergrant.UserID, usergrant.ProjectID, usergrant.ProjectGrantID)
|
||||
func (c *Commands) checkUserGrantPreCondition(ctx context.Context, usergrant *domain.UserGrant, resourceOwner string) error {
|
||||
preConditions := NewUserGrantPreConditionReadModel(usergrant.UserID, usergrant.ProjectID, usergrant.ProjectGrantID, resourceOwner)
|
||||
err := c.eventstore.FilterToQueryReducer(ctx, preConditions)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -294,7 +294,7 @@ func (c *Commands) checkUserGrantPreCondition(ctx context.Context, usergrant *do
|
||||
if !preConditions.UserExists {
|
||||
return caos_errs.ThrowPreconditionFailed(err, "COMMAND-4f8sg", "Errors.User.NotFound")
|
||||
}
|
||||
if !preConditions.ProjectExists {
|
||||
if usergrant.ProjectGrantID == "" && !preConditions.ProjectExists {
|
||||
return caos_errs.ThrowPreconditionFailed(err, "COMMAND-3n77S", "Errors.Project.NotFound")
|
||||
}
|
||||
if usergrant.ProjectGrantID != "" && !preConditions.ProjectGrantExists {
|
||||
|
||||
@@ -89,17 +89,19 @@ type UserGrantPreConditionReadModel struct {
|
||||
UserID string
|
||||
ProjectID string
|
||||
ProjectGrantID string
|
||||
ResourceOwner string
|
||||
UserExists bool
|
||||
ProjectExists bool
|
||||
ProjectGrantExists bool
|
||||
ExistingRoleKeys []string
|
||||
}
|
||||
|
||||
func NewUserGrantPreConditionReadModel(userID, projectID, projectGrantID string) *UserGrantPreConditionReadModel {
|
||||
func NewUserGrantPreConditionReadModel(userID, projectID, projectGrantID, resourceOwner string) *UserGrantPreConditionReadModel {
|
||||
return &UserGrantPreConditionReadModel{
|
||||
UserID: userID,
|
||||
ProjectID: projectID,
|
||||
ProjectGrantID: projectGrantID,
|
||||
ResourceOwner: resourceOwner,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,17 +117,18 @@ func (wm *UserGrantPreConditionReadModel) Reduce() error {
|
||||
case *user.UserRemovedEvent:
|
||||
wm.UserExists = false
|
||||
case *project.ProjectAddedEvent:
|
||||
wm.ProjectExists = true
|
||||
if wm.ProjectGrantID == "" && wm.ResourceOwner == e.Aggregate().ResourceOwner {
|
||||
wm.ProjectExists = true
|
||||
}
|
||||
case *project.ProjectRemovedEvent:
|
||||
wm.ProjectExists = false
|
||||
case *project.GrantAddedEvent:
|
||||
if wm.ProjectGrantID == e.GrantID {
|
||||
if wm.ProjectGrantID == e.GrantID && wm.ResourceOwner == e.GrantedOrgID {
|
||||
wm.ProjectGrantExists = true
|
||||
wm.ExistingRoleKeys = e.RoleKeys
|
||||
}
|
||||
case *project.GrantChangedEvent:
|
||||
if wm.ProjectGrantID == e.GrantID {
|
||||
wm.ProjectGrantExists = true
|
||||
wm.ExistingRoleKeys = e.RoleKeys
|
||||
}
|
||||
case *project.GrantRemovedEvent:
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
caos_errs "github.com/zitadel/zitadel/internal/errors"
|
||||
@@ -16,7 +18,6 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/repository/project"
|
||||
"github.com/zitadel/zitadel/internal/repository/user"
|
||||
"github.com/zitadel/zitadel/internal/repository/usergrant"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
func TestCommandSide_AddUserGrant(t *testing.T) {
|
||||
@@ -149,6 +150,48 @@ func TestCommandSide_AddUserGrant(t *testing.T) {
|
||||
err: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "project on other org, precondition error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
user.NewHumanAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
"username1",
|
||||
"firstname1",
|
||||
"lastname1",
|
||||
"nickname1",
|
||||
"displayname1",
|
||||
language.German,
|
||||
domain.GenderMale,
|
||||
"email1",
|
||||
true,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
project.NewProjectAddedEvent(context.Background(),
|
||||
&project.NewAggregate("project1", "org1").Aggregate,
|
||||
"projectname1", true, true, true,
|
||||
domain.PrivateLabelingSettingUnspecified,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.NewMockContextWithPermissions("", "org2", "user", []string{domain.RoleProjectOwner}),
|
||||
userGrant: &domain.UserGrant{
|
||||
UserID: "user1",
|
||||
ProjectID: "project1",
|
||||
},
|
||||
resourceOwner: "org2",
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "project roles not existing, precondition error",
|
||||
fields: fields{
|
||||
@@ -296,6 +339,66 @@ func TestCommandSide_AddUserGrant(t *testing.T) {
|
||||
err: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "project grant on other org, precondition error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
user.NewHumanAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
"username1",
|
||||
"firstname1",
|
||||
"lastname1",
|
||||
"nickname1",
|
||||
"displayname1",
|
||||
language.German,
|
||||
domain.GenderMale,
|
||||
"email1",
|
||||
true,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
project.NewProjectAddedEvent(context.Background(),
|
||||
&project.NewAggregate("project1", "org1").Aggregate,
|
||||
"projectname1", true, true, true,
|
||||
domain.PrivateLabelingSettingUnspecified,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
project.NewRoleAddedEvent(context.Background(),
|
||||
&project.NewAggregate("project1", "org1").Aggregate,
|
||||
"rolekey1",
|
||||
"rolekey",
|
||||
"",
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
project.NewGrantAddedEvent(context.Background(),
|
||||
&project.NewAggregate("project1", "org1").Aggregate,
|
||||
"projectgrant1",
|
||||
"org3",
|
||||
[]string{"rolekey1"},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.NewMockContextWithPermissions("", "org2", "user", []string{domain.RoleProjectOwner}),
|
||||
userGrant: &domain.UserGrant{
|
||||
UserID: "user1",
|
||||
ProjectID: "project1",
|
||||
ProjectGrantID: "projectgrant1",
|
||||
RoleKeys: []string{"rolekey1"},
|
||||
},
|
||||
resourceOwner: "org2",
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "usergrant for project, ok",
|
||||
fields: fields{
|
||||
|
||||
Reference in New Issue
Block a user