Pular para o conteúdo principal
Como o SDK funciona

Esta página ainda não foi traduzida: mostrando a versão em inglês.

Access & Roles

Os papéis são compostos, nunca fixos no código. Permissões atômicas se combinam em papéis; os papéis controlam o acesso aos dados até a linha e a coluna e decidem quais interfaces de módulo um build chega a ver. Isso substitui a divisão entre chave de cliente e chave de servidor: a credencial aponta para uma identidade, e os papéis dela são resolvidos a cada requisição.

Quando usar

  • Você precisa de uma credencial mais restrita que “cliente” ou “servidor”: por trás dela, papéis (role) compostos são resolvidos a cada requisição.
  • O acesso aos dados precisa parar em linhas e colunas: escopo por região, máscaras para dados pessoais, prestadores de serviço com acesso somente leitura.
  • Um build só deve ver as interfaces que o papel dele libera: para um visitante, expulsar e fechar simplesmente não existem.
  • A sua UI precisa desabilitar botões com precisão: CanI avalia a mesma política que o servidor vai aplicar.
  • Dispensável quando os presets que vêm com a plataforma (player, room-owner, seller, …) já correspondem aos seus atores. Todo módulo os respeita por padrão; o catálogo completo está em Conceitos principais.

Quem faz o quê

AtorO que faz nesta página
operatordeclara papéis e políticas, define limites por linha e por coluna, concede papéis, emite chaves
match-organizerequipe do torneio: tem uma chave com papéis compostos, controla as inscrições, não pode fazer reembolsos
todo atorverifica CanI antes de agir; vê só as interfaces que tem liberadas

Resumo

Declare entry-validator com limites por linha e por coluna, conceda o papel e verifique CanI antes de agir
[Role("entry-validator")]
public class EntryValidator
{
    [Allow(Rooms.Membership.Administer)] public Permit GateEntries;
    [Allow(Data.Records.Read, table: "player_profile", rows: "banned == false",
           columns: "id, display_name")] public Permit SeeProfiles;
}

await PlayServ.Access.Grant(staffId, Roles.EntryValidator, Roles.MatchOrganizer);
var key = await PlayServ.Access.IssueKey(staffId);   // the credential names no roles

// any actor, before attempting an operation:
if (await PlayServ.Access.CanI(Commerce.Orders.Administer)) Hud.ShowRefund();
@Role('entry-validator')
export class EntryValidator {
  @Allow(Rooms.membership.administer) gateEntries: Permit;
  @Allow(Data.records.read, { table: 'player_profile', rows: 'banned == false',
                              columns: ['id', 'display_name'] }) seeProfiles: Permit;
}

await playserv.access.grant(staffId, Roles.entryValidator, Roles.matchOrganizer);
const key = await playserv.access.issueKey(staffId);  // the credential names no roles

// any actor, before attempting an operation:
if (await playserv.access.canI(Commerce.orders.administer)) hud.showRefund();
@role("entry-validator")
class EntryValidator:
    gate_entries = allow(rooms.membership.administer)
    see_profiles = allow(data.records.read, table="player_profile",
                         rows="banned == false", columns=["id", "display_name"])

await playserv.access.grant(staff_id, roles.ENTRY_VALIDATOR, roles.MATCH_ORGANIZER)
key = await playserv.access.issue_key(staff_id)   # the credential names no roles

# any actor, before attempting an operation:
if await playserv.access.can_i(commerce.orders.administer):
    hud.show_refund()
Em breve — Go

Ainda não está decidido como declarar com atributos em Go (O-1). Os exemplos chegam quando a forma de escrita for escolhida.

// declarations compile into the same pushed model — playserv push from the UE project or CI
USTRUCT(PSRole = "entry-validator")
struct FEntryValidator
{
    GENERATED_BODY()

    UPROPERTY(PSAllow = (Atom = "Rooms.Membership.Administer"))
    FPSPermit GateEntries;

    UPROPERTY(PSAllow = (Atom = "Data.Records.Read", Table = "player_profile",
                         Rows = "banned == false", Columns = "id, display_name"))
    FPSPermit SeeProfiles;
};

// granting is an operator act; a build checks what its identity resolves to
const FPSActor Me = Client->Whoami();   // which interfaces this actor unlocks
Client->Access->CanI(TEXT("Commerce.Orders.Administer"),
    TPSOnResult<bool>::CreateWeakLambda(this, [this](const TPSResult<bool>& Result)
    {
        if (!Result.HasValue()) { return; }
        if (Result.Value()) { Hud->ShowRefund(); }
    }));
// co_await support ships later: a built-in SDK coroutine wrapper that respects Unreal's GC and threading.
// the same `[Role]` / `[Allow]` declaration as the server tab, on the Unity 2021.3 runtime
var me = playserv.Whoami();               // which interfaces this actor unlocks
if (await playserv.Access.CanI(Commerce.Orders.Administer)) hud.ShowRefund();

Uma permissão atômica é um par: um recurso e um de quatro verbos — read, write, execute, administer. O conjunto de verbos é fixo; um caso que não se encaixa nele divide o recurso em vez de aumentar a lista. Por isso, controlar a entrada de outra pessoa é Rooms.Membership.Administer, e não um verbo ValidateEntry só para isso: agir sobre a participação de outro ator é administração, enquanto entrar você mesmo é Rooms.Membership.Write no mesmo recurso.

O modelo

O ACL de dados é papel × operação × predicado de linhas × máscara de campos — um único modelo, idêntico seja ele escrito no código, pela API ou na grade de papéis do painel.

Do que o acesso é feito.

TermoO que é
permissão atômicaum par recurso × verbo. Os quatro verbos são read (buscar, selecionar, assinar), write (criar, alterar, excluir e agir por si mesmo — entrar, sair), execute (chamar uma função, aplicar uma habilidade) e administer (agir sobre os outros: expulsar, fechar, forçar uma mudança de estado)
papelum conjunto nomeado de permissões atômicas. Pode incluir outro papel
preset de papelvem com a plataforma, construído sobre permissões atômicas, e continua funcionando sem mudanças para quem já o usa em produção. É um ponto de partida, não uma restrição: um projeto declara papéis próprios com as mesmas permissões atômicas
predicado de linhasquais linhas — um predicado booleano sobre valores da sessão
máscara de camposquais campos, declarada por papel e por operação

O que cada credencial libera.

CredencialO que libera
chave de jogadorvai dentro de um build da engine; o jogador por trás dela chega com o login, e o build vê as linhas cl de toda tabela de operações
chave de hostfica com um servidor dedicado ou um cliente mestre (master-client), e os papéis dela liberam as linhas mc
código publicadoroda com o papel backend-service do projeto — é isso que o Authoritative = true de um ranking verifica
um hook registradonão concede nada a mais: a sua função mantém o papel com que foi publicada

A legenda das tags (fn / cl / mc / adm) fica em Conceitos principais.

O que vale para toda verificação.

SempreO que é
uma credencialnão carrega lista de papéis: aponta para uma identidade, e os papéis são resolvidos no servidor a cada requisição. Uma revogação invalida na hora a resolução em cache, sem esperar o limite de desatualização declarado
a delegaçãomuda o escopo, nunca a capacidade: agir em nome de um jogador muda quais linhas ficam visíveis e a quem uma escrita é atribuída, mas não concede nenhuma operação que o ator já não tivesse
o verboresponde que tipo de efeito, e o predicado responde quais linhas. Se dois casos diferem só em de quem é a linha, é um predicado; se o próprio efeito é outro, é outra operação e talvez outro verbo — por isso “expulsar” é administer, e não write com um predicado amplo
um donosempre vê a si mesmo, diga o predicado o que disser
a visibilidadenão é segurança — uma otimização de canais e uma permissão são mecanismos diferentes, e nenhum substitui o outro
um módulo desativadonão tem interface: estar ativado é uma propriedade do build, então a geração de código não emite nada para um módulo desativado, e uma chamada indisponível vira erro de compilação, e não uma recusa em runtime
a interface de um módulosegue o ator, não o lado (veja Quem toma as decisões): um build room-visitor vê entrar, sair e ler; um build room-owner vê também expulsar, fechar e configurar; e whoami informa quais interfaces o ator atual libera

Quem distribui os papéis. Conceder e revogar o papel de um jogador, assim como o papel padrão que o projeto declara para um jogador novo, são operações de Auth & Players — esse módulo é dono das identidades, e o papel é resolvido pela identidade que está na credencial.

Erros

  • O que um predicado esconde responde not found, não forbidden: senão a própria recusa contaria a quem chamou que aquilo existe.
  • Um direito que quem chama não tem responde forbidden quando a existência do alvo não é segredo, e a resposta diz o que faltou em vez de falhar sem explicação.
  • Um campo fora da máscara não aparece na resposta, em vez de vir presente e vazio: um valor vazio e um valor mascarado seriam indistinguíveis.
  • Um papel que inclui a si mesmo, diretamente ou por uma cadeia, é um erro de configuração — recusado já como declaração, e não resolvido em runtime.
  • A delegação nunca amplia a capacidade: uma chamada que o ator não poderia fazer por conta própria é recusada quando feita em nome de um jogador.

Limites

Os números chegam com o capítulo de limites da plataforma; o que acontece em cada teto já está definido.

  • O tamanho de uma seleção sob um predicado de linhas é limitado, e o modelo de ACL declara esse limite em vez de descobri-lo na prática. Uma leitura acima do teto recebe o teto em linhas, mais o marcador de que foi cortada — nunca uma página menor sem aviso.
  • O limite de desatualização de uma permissão resolvida é declarado, e uma revogação não espera por ele: invalida na hora.