feat: release Dever 0.1.4 with enforceable project guidance
This commit is contained in:
1 parent
201bdee372
commit
89629c2197
86 files changed
+2798
-338
No files matched your search
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"database": {
|
||||
"default": {
|
||||
"type": "sqlite",
|
||||
"path": "data/db/platform.db",
|
||||
"tenant_directory": "data/tenants"
|
||||
}
|
||||
},
|
||||
"tenant": { "database": "default" },
|
||||
"auth": {
|
||||
"providers": {
|
||||
"session": {
|
||||
"verify": "access.session.verify",
|
||||
"jwtSecret": "replace-this-example-secret-before-deployment",
|
||||
"ttlSeconds": 3600
|
||||
}
|
||||
}
|
||||
},
|
||||
"sites": { "admin": { "path": "admin", "auth": "session" } },
|
||||
"http": { "host": "127.0.0.1", "port": 8080 },
|
||||
"log": { "level": "info" }
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
type Identity {
|
||||
id: Text
|
||||
user_id: access.user.model.id?
|
||||
tenant_id: access.tenant.model.id?
|
||||
}
|
||||
|
||||
verify(claims: dever.auth.Claims) (identity: Identity) {
|
||||
identity = find_session(uuid.parse(claims.session), claims.tenant, claims)
|
||||
}
|
||||
|
||||
find_session(session_id: Uuid, selected_key: Text, claims: dever.auth.Claims) (
|
||||
identity: Identity
|
||||
) {
|
||||
stored = model.first(
|
||||
{
|
||||
where = uuid == session_id and subject == claims.subject and site == claims.site and tenant_key == selected_key and revoked == false and expires_at > dever.time.now(
|
||||
)
|
||||
}
|
||||
)
|
||||
identity = verified(stored)
|
||||
}
|
||||
|
||||
find_session(session_id: null, selected_key: Text?, claims: dever.auth.Claims) (
|
||||
identity: Identity
|
||||
) {
|
||||
fail(dever.api.Error.Unauthorized)
|
||||
}
|
||||
|
||||
find_session(session_id: Uuid, selected_key: null, claims: dever.auth.Claims) (
|
||||
identity: Identity
|
||||
) {
|
||||
fail(dever.api.Error.Unauthorized)
|
||||
}
|
||||
|
||||
verified(stored: model.Session) (identity: Identity) {
|
||||
access.user.require_active(stored.user_id)
|
||||
access.tenant.require_active(stored.tenant_id, stored.tenant_key)
|
||||
require_membership(
|
||||
model.membership.exists(
|
||||
{
|
||||
where = user_id == stored.user_id and tenant_id == stored.tenant_id and active == true
|
||||
}
|
||||
)
|
||||
)
|
||||
identity = Identity {
|
||||
id = stored.subject
|
||||
user_id = stored.user_id
|
||||
tenant_id = stored.tenant_id
|
||||
}
|
||||
}
|
||||
|
||||
verified(stored: null) (identity: Identity) {
|
||||
fail(dever.api.Error.Unauthorized)
|
||||
}
|
||||
|
||||
require_membership(active: true) () {}
|
||||
|
||||
require_membership(active: false) () {
|
||||
fail(dever.api.Error.Unauthorized)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
global type Session {
|
||||
uuid: Uuid generated unique
|
||||
subject: Text
|
||||
user_id: access.user.model.id
|
||||
tenant_id: access.tenant.model.id
|
||||
tenant_key: Text
|
||||
site: Text
|
||||
expires_at: DateTime
|
||||
revoked: Bool default false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
global type Membership {
|
||||
user_id: access.user.model.id
|
||||
tenant_id: access.tenant.model.id
|
||||
active: Bool default true
|
||||
}
|
||||
|
||||
unique(user_id, tenant_id)
|
||||
@@ -0,0 +1,9 @@
|
||||
require_active(tenant_id: model.id, tenant_key: Text) () {
|
||||
domain.require_active(
|
||||
model.exists(
|
||||
{
|
||||
where = id == tenant_id and key == tenant_key and active == true
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
require_active(active: true) () {}
|
||||
|
||||
require_active(active: false) () {
|
||||
fail(dever.api.Error.Unauthorized)
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
global type Tenant {
|
||||
key: Text unique
|
||||
active: Bool default true
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
require_active(user_id: model.id) () {
|
||||
domain.require_active(
|
||||
model.exists(
|
||||
{
|
||||
where = id == user_id and active == true
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
require_active(active: true) () {}
|
||||
|
||||
require_active(active: false) () {
|
||||
fail(dever.api.Error.Unauthorized)
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
global type User {
|
||||
uuid: Uuid generated unique
|
||||
active: Bool default true
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
rest model
|
||||
@@ -0,0 +1,3 @@
|
||||
normalize(value: Text) (title: Text) pure {
|
||||
title = text.trim(value)
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
type Article {
|
||||
title: Text(1, 200) create = domain.normalize(input) replace = domain.normalize(input)
|
||||
body: Text
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
public get ready = app.status
|
||||
@@ -0,0 +1,3 @@
|
||||
status() (healthy: Bool) {
|
||||
healthy = true
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
title() () {
|
||||
assert_eq(domain.normalize(" Draft "), "Draft")
|
||||
}
|
||||
Reference in new issue
Block a user