Compare commits

..

54 Commits
v0.2 ... main

Author SHA1 Message Date
f3f53dafb6 Add some links + info to readme 2025-03-03 22:50:42 +00:00
c5a59880ad remove useless MR/PR templates 2025-02-28 21:59:18 +01:00
120db0a68a Remove docs dir because we put information at centralized docs.fab-access.og 2025-02-28 21:57:50 +01:00
ce49e3d07c Synchronize documentation with in-code docs and remove them from capnp file 2025-02-24 15:21:42 +00:00
Nadja Reitzenstein
ec8352c6ae Add vendor API endpoint 2023-05-24 13:41:30 +02:00
Nadja Reitzenstein
cde4677575 prodable machines 2023-02-14 17:03:26 +01:00
TheJoKlLa
19f20f5154 Update usersystem.capnp 2022-05-10 21:04:13 +00:00
Nadja Reitzenstein
f1fa024613 Yeah we should link to the english one from the german one 2022-04-30 19:49:12 +02:00
Nadja Reitzenstein
54508a7944 Update links to respective other language template 2022-04-30 19:47:59 +02:00
Nadja Reitzenstein
5e7b7d9949 Rename Templates, parentheses break gitlab 2022-04-30 19:47:30 +02:00
Nadja Reitzenstein
544402ea39 Test template 4, 3 successful 2022-04-30 19:43:46 +02:00
Nadja Reitzenstein
6043448645 Test template 3 2022-04-30 19:43:03 +02:00
Nadja Reitzenstein
d2e46cc6d2 Test template 2 2022-04-30 19:42:19 +02:00
Nadja Reitzenstein
1e2f1b40a9 Adds a trivial test template because something is breaking 2022-04-30 19:41:48 +02:00
Nadja Reitzenstein
8f1e528ba8 Adds issue templates for feature requests 2022-04-30 19:37:37 +02:00
dequbed
244eb9bd1b Merge branch 'feature/fallible' into 'main'
User management and related API improvements

See merge request fabinfra/fabaccess/fabaccess-api!20
2022-04-28 18:19:48 +00:00
Nadja Reitzenstein
d04d930bd3 Add an 'invalid password' error 2022-04-28 20:12:16 +02:00
Nadja Reitzenstein
c00a274a16 Add deprecation comment 2022-04-28 20:11:08 +02:00
Nadja Reitzenstein
93f130873e stay backwards compatible 2022-04-28 20:10:06 +02:00
Nadja Reitzenstein
750ae0c34b Make the API be more proper regarding user mgmnt 2022-04-28 19:01:15 +02:00
Nadja Reitzenstein
f02afb3736 Parameters should remain named 2022-04-27 20:24:07 +02:00
Nadja Reitzenstein
aea03aabe3 Make all fields that may not have an User be Optional(User)
Fixes #24
2022-04-22 20:02:52 +02:00
Nadja Reitzenstein
aa006507c4 return Optional value for searches 2022-04-22 19:32:17 +02:00
TheJoKlLa
049b183f96 Merge branch 'fix/MachineUserSystemInterface' into 'main'
Changed MachineInterface and UserInterface to Field from Method

See merge request fabinfra/fabaccess/fabaccess-api!19
2022-04-21 21:54:06 +00:00
Nadja Reitzenstein
2406e77fb9 fix4 2022-04-21 20:21:10 +02:00
Nadja Reitzenstein
f8b317bb15 fix3 2022-04-21 20:19:59 +02:00
Nadja Reitzenstein
d006351b6f fix2 2022-04-21 20:17:03 +02:00
Nadja Reitzenstein
2977a0f5d9 fix 2022-04-21 20:08:55 +02:00
TheJoKlLa
ea388f998c Changed MachineInterface and UserInterface to Field from Method 2022-04-20 10:50:01 +00:00
Nadja Reitzenstein
c9283ebd69 initial data like that makes no sense 2022-03-12 14:59:38 +01:00
Nadja Reitzenstein
c20703dd5b return structs directly 2022-03-12 14:37:25 +01:00
Nadja Reitzenstein
9c745b79bb make compile for Rust 2022-03-12 01:57:12 +01:00
dequbed
557f37b7cf Merge branch 'develop' into 'main'
Develop improvements

Closes #14 and #12

See merge request fabinfra/fabaccess/fabaccess-api!18
2022-03-11 23:08:24 +00:00
Nadja Reitzenstein
564a69ef35 Slimming down the useless parts 2022-03-12 00:00:49 +01:00
Nadja Reitzenstein
63e74aacc0 Improve Auth & Session 2022-03-12 00:00:49 +01:00
Nadja Reitzenstein
277133dd35 Make Authentication return an authenticated Bootstrap instead
Fixes: #12
Fixes: #14
2022-03-12 00:00:49 +01:00
TheJoKlLa
6b0aba90a9 Fixed: C# Name for TakeoverInterface 2022-03-12 00:00:05 +01:00
TheJoKlLa
97ca7deba1 Added: instructorUser for tracking of the user who has released the machine for a user without the permission for the machine. && Added; releasefortakeover to get from inuse state to totakeover state 2022-03-11 23:56:01 +01:00
TheJoKlLa
76b886140d Fixed IDs 2022-03-09 16:59:28 +01:00
TheJoKlLa
bda6c0be37 Fixed: InfosExtended to ManageInterface && Added: Machine totakeover state 2022-03-09 16:02:40 +01:00
Nadja Reitzenstein
18ed9c2ae6 Merge branch 'v0.3' into 'main'
Features required for v0.3

Closes #17 and #20

See merge request fabinfra/fabaccess/fabaccess-api!16
2022-02-04 14:36:09 +01:00
Nadja Reitzenstein
3ccfcc2b35 make compile 2022-01-05 20:20:38 +01:00
Kai Jan Kriegel
ae1c762f3e Revert "render ADRs via gitlab pages"
This reverts commit a9ea6120733afd9d75ba8872faa0c5bb41ff3174.
2022-01-05 20:18:58 +01:00
Nadja Reitzenstein
4925081753 correct @kjkriegel's nick 2022-01-05 19:57:02 +01:00
Kai Kriegel
64863ec96c try gitbook 2022-01-05 18:22:54 +00:00
Kai Kriegel
a9ea612073 render ADRs via gitlab pages 2022-01-05 18:07:02 +00:00
Nadja Reitzenstein
bb88fb1832 Add category field to Machines
Fixes: #20
2022-01-05 17:44:30 +01:00
Nadja Reitzenstein
8033653d2c fix links in ADR-0001 2022-01-05 17:34:24 +01:00
Nadja Reitzenstein
5de7dc2ef3 Transport encryption ADR 2022-01-05 17:31:29 +01:00
Nadja Reitzenstein
f1a7e3882d use MADR 2022-01-05 16:43:58 +01:00
Nadja Reitzenstein
89edea3ead Make const defs UPPERCASE
This, f1bd4514 and b12a5601 implement proper versioning, so:

Fixes: #17
2022-01-05 16:24:39 +01:00
Nadja Reitzenstein
b12a5601c3 make getServerVersion able to return more informational output 2022-01-05 16:06:39 +01:00
TheJoKlLa
f1bd45141e Changed API Version ID to get backward compatibility in Bootstrap Interface 2021-12-22 19:13:42 +00:00
TheJoKlLa
d34c06c48e Add API and Server Version 2021-12-22 19:08:23 +00:00
10 changed files with 188 additions and 200 deletions

5
.gitignore vendored
View File

@ -1,2 +1,7 @@
tags tags
*.cs *.cs
# MADR
/node_modules/
/package-lock.json
/package.json

View File

@ -7,3 +7,10 @@ When returning an Interface it may be required to append a dummy valueto work ar
- whoami @4 () -> ( you :Api.User ); - whoami @4 () -> ( you :Api.User );
+ whoami @4 () -> ( you :Api.User, dummy :UInt8 = 0 ); + whoami @4 () -> ( you :Api.User, dummy :UInt8 = 0 );
``` ```
## Docs
A lot of information (concepts, usage, decisions) about this API can be found at [docs.fab-access.org](https://docs.fab-access.org/books/schnittstellen-und-apis/page/fabaccess-api#bkmrk-fabaccess-api).
See also:
- [pyfabapi (Python Wrapper)](https://gitlab.com/fabinfra/fabaccess/pyfabapi)
- [FabAccess-API-cs (C# implementation)](https://gitlab.com/fabinfra/fabaccess/fabaccess-api-cs)

View File

@ -1,135 +1,76 @@
@0xb9cffd29ac983e9f; @0xb9cffd29ac983e9f;
using Rust = import "programming_language/rust.capnp"; using Rust = import "programming_language/rust.capnp";
$Rust.parentModule("schema"); $Rust.parentModule("schema");
using CSharp = import "programming_language/csharp.capnp"; using CSharp = import "programming_language/csharp.capnp";
$CSharp.namespace("FabAccessAPI.Schema"); $CSharp.namespace("FabAccessAPI.Schema");
using User = import "user.capnp".User; using Session = import "connection.capnp".Session;
interface AuthenticationSystem {
mechanisms @0 () -> ( mechs :List(Text) );
# Get the list of mechanisms supported by the server
start @1 ( request :Request ) -> ( response :Response );
# Initiate an authentication exchange
# NOTE: Calling start() after an authentication exchange has already
# finished is undefined behaviour. If you want to double-authenticate call
# auth() from connection.capnp again to get a fresh capability you can use.
# This may however return NULL if you are not allowed to authenticate twice.
step @2 ( response :Data ) -> ( response :Response );
# Respond to a challenge with more data
# NOTE: As with start() calling this after having received an outcome is
# undefined behaviour.
abort @3 () -> ();
# Abort the current exchange. This may be sent by both client and server
# at any point during the exchange. It MUST not be sent by a server
# after sending an outcome or by a client after receiving an outcome.
# A server receiving an abort after sending an outcome but before
# receiving any other message MUST respect the abort.
whoami @4 () -> ( you :User, dummy :UInt8 = 0 );
# Returns NULL if not authenticated and an User object if authenticated.
}
struct Request {
mechanism @0 :Text; # The SASL mechanism name.
initialResponse :union {
# A client may send some intial data when requesting an auth exchange.
# According to RFC4422 section 4.3a an implementation MUST be able to
# distinguish between an empty initial reponse and no initial response.
none @1 :Void;
# No initial reponse is being sent.
# The lowest numbered field in an union is the default value in Cap'n
# Proto.
initial @2 :Data;
# A response may be any sequence of octets, including zero-length
# sequences and zero-valued octets.
}
}
struct Response { struct Response {
enum Result { enum Error {
# Result code of the outcome aborted @0;
successful @0; # This authentication exchange was aborted by either side.
badMechanism @1; badMechanism @1;
# The server does not support this mechanism in this context. # The server does not support this mechanism in this context.
unwilling @2; invalidCredentials @2;
# Generic "I'm sorry dave, I can't do that" response. MAY be set for any # The exchange was valid, but the provided credentials are invalid. This may mean that the
# reason, all reasons or no reason at all. # authcid is not known to the server or that the password/certificate/key/ticket/etc is not
# A server SHOULD set the `action` and `helpText` fields as appropiate. # correct.
# This code SHOULD only be sent if no other value is more fitting.
invalidCredentials @3; failed @3;
# The exchange was valid, but the provided credentials are invalid. This # A generic failed result. A server sending this result MUST set the `action` field to
# may mean that the authcid is not known to the server or that the # indicate whether this is a temporary or permanent failure and SHOULD set `description` to
# password/certificate/key/etc. is not correct. # a human-readable error message.
unauthorized @4;
# The given authcid is not authorized to act as the requested authzid.
# This MAY also be returned for the cases `authzid == NULL` or
# `authzid == authcid`, for example because login is disabled for that
# authcid.
malformedAuthZid @5;
# The provided authzid is malformed in some way.
failed @6;
# A generic failed result. A server sending this result MUST set the
# `action` field to indicate whether this is a temporary or permanent
# failure and SHOULD set `helpText` to a human-readable error message.
} }
enum Action {
# In case of a unsuccessful outcome, how should a client proceed?
unset @0;
# Not a unsuccessful outcome, or the server doesn't know either.
# Also, the default value
retry @1;
# A client should just try again, potentially after prompting the user
# to enter their credentials again.
wait @2;
# The client should wait and try again later. This MAY mean that
# whatever failure happened was temporary or the server is applying
# rate-limiting to the connection.
permanent @3;
# The issue appears to the server as being permanent. Another try is
# very likely to return the exact same result. In most cases the user
# should notify the responsible system administrator.
}
union { union {
challence @0 :Data; failed :group {
outcome :group { code @0 :Error;
result @1 :Result; # Result code # Error code indicating the cause of the error
action @2 :Action; # Hints for the client how to proceed in case of an error additionalData @1 :Data;
# Some mechanisms will send additional data after an error
}
# Some kind of error happened. This in the first entry in the union because it is the
# default set value meaning if a server fails to set any of the values, indicating some
# pretty severe server bugs, it is parsed as an "aborted" error.
challenge @2 :Data;
# The data provided so far is not enough to authenticate the user. The data MAY be a
# NULL-ptr or a non-NULL list ptr of zero bytes which clients MUST pass to their SASL
# implementation as "no data" and "some data of zero length" respectively.
helpText @3 :Text; # Human-readable further information in case of an error successful :group {
# The exchange was successful and a new session has been created for the authzid that
# was established by the SASL exchange.
additionalData :union { session @3 :Session;
# Additional data that may be sent by the server to the client after a # The session that was created. It grants access to all capabilities the connecting
# successful authentication exchange. # party has permissions for.
none @4 :Void; additionalData @4 :Data;
# No additional data is being sent. This MUST be set on unsuccessful # SASL may send additional data with the successful result. This MAY be a NULL-ptr or a
# outcomes. # non-NULL list ptr of zero bytes which clients MUST pass to their SASL implementation
# as "no additional data" and "some additional data of zero length" respectively.
additional @5 :Data;
# Additional data may be any sequence of octets, including zero-length
# sequences and zero-value octets.
}
} }
} }
} }
interface Authentication {
step @0 ( data: Data ) -> Response;
# Respond to a challenge with more data. A client MUST NOT call this after having received an
# "successful" response.
abort @1 ();
# Abort the current exchange. This will invalidate the Authentication making all further calls
# to `step` return an error response. A client MUST NOT call this function after
# having received an "successful" response.
# A server will indicate that they have aborted an authentication exchange by replying with an
# "aborted" Error to the next `step` call. A server SHOULD directly terminate the underlying stream
# after sending this response. The server MAY after a short grace period terminate the stream
# without sending a response if no call to `step` was received by the client.
}

View File

@ -6,18 +6,44 @@ $Rust.parentModule("schema");
using CSharp = import "programming_language/csharp.capnp"; using CSharp = import "programming_language/csharp.capnp";
$CSharp.namespace("FabAccessAPI.Schema"); $CSharp.namespace("FabAccessAPI.Schema");
using AuthenticationSystem = import "authenticationsystem.capnp".AuthenticationSystem; using Authentication = import "authenticationsystem.capnp".Authentication;
using MachineSystem = import "machinesystem.capnp".MachineSystem; using MachineSystem = import "machinesystem.capnp".MachineSystem;
using UserSystem = import "usersystem.capnp".UserSystem; using UserSystem = import "usersystem.capnp".UserSystem;
using PermissionSystem = import "permissionsystem.capnp".PermissionSystem; using PermissionSystem = import "permissionsystem.capnp".PermissionSystem;
const apiVersionMajor :Int32 = 0;
const apiVersionMinor :Int32 = 3;
const apiVersionPatch :Int32 = 0;
struct Version
{
major @0 :Int32;
minor @1 :Int32;
patch @2 :Int32;
}
interface Bootstrap interface Bootstrap
{ {
authenticationSystem @0 () -> ( authenticationSystem : AuthenticationSystem ); getAPIVersion @0 () -> Version;
machineSystem @1 () -> ( machineSystem : MachineSystem ); getServerRelease @1 () -> ( name :Text, release :Text );
# Returns the server implementation name and version/build number
userSystem @2 () -> ( userSystem : UserSystem ); # Designed only for human-facing debugging output so should be informative over machine-readable
# Example: ( name = "bffhd", release = "0.3.1-f397e1e [rustc 1.57.0 (f1edd0429 2021-11-29)]")
permissionSystem @3 () -> ( permissionSystem : PermissionSystem ); mechanisms @2 () -> ( mechs: List(Text) );
# Get a list of Mechanisms this server allows in this context.
createSession @3 ( mechanism :Text ) -> ( authentication :Authentication );
# Create a new session with the server that you wish to authenticate using `mechanism`.
# Using pipelining makes this one-roundtrip capable without explicit initial data support.
}
struct Session {
machineSystem @0 : MachineSystem;
userSystem @1 : UserSystem;
permissionSystem @2 : PermissionSystem;
vendor @3 :AnyPointer;
# Vendor-specific APIs outside the normal API stability
} }

View File

@ -25,4 +25,21 @@ struct UUID {
struct KeyValuePair { struct KeyValuePair {
key @0 :Text; key @0 :Text;
value @1 :Text; value @1 :Text;
}
struct Optional(T) {
union {
nothing @0 :Void;
just @1 :T;
}
}
struct Fallible(T, E) {
# Some operations can fail in several expected ways.
# In those cases returning an `Optional` doesn't transfer information about the way that the
# operation failed. `Fallible` contains this information in the generic `E` type.
union {
failed @0 :E;
successful @1 :T;
}
} }

View File

@ -7,6 +7,7 @@ using CSharp = import "programming_language/csharp.capnp";
$CSharp.namespace("FabAccessAPI.Schema"); $CSharp.namespace("FabAccessAPI.Schema");
using General = import "general.capnp"; using General = import "general.capnp";
using Optional = General.Optional;
using User = import "user.capnp".User; using User = import "user.capnp".User;
using Space = import "space.capnp".Space; using Space = import "space.capnp".Space;
@ -18,10 +19,12 @@ struct Machine {
blocked @3; blocked @3;
disabled @4; disabled @4;
reserved @5; reserved @5;
totakeover @6;
} }
struct MachineInfoExtended { struct MachineInfoExtended {
currentUser @0 :User; currentUser @0 :Optional(User);
transferUser @1 :User; lastUser @1 :Optional(User);
instructorUser @2 :Optional(User);
} }
struct Reservation { struct Reservation {
@ -35,17 +38,16 @@ struct Machine {
name @2 :Text; name @2 :Text;
description @3 :Text; description @3 :Text;
state @4 :MachineState; state @4 :MachineState;
manager @5:User; manager @5:Optional(User);
wiki @13 :Text; wiki @13 :Text;
urn @14 :Text; urn @14 :Text;
category @15 :Text;
info @6 :Info; info @6 :Info;
interface Info $CSharp.name("InfoInterface") { interface Info $CSharp.name("InfoInterface") {
getMachineInfoExtended @0 () -> ( machineInfoExtended :MachineInfoExtended, dummy :UInt8 = 0); getPropertyList @0 () -> ( propertyList :List(General.KeyValuePair) );
getPropertyList @1 () -> ( propertyList :List(General.KeyValuePair) ); getReservationList @1 () -> ( reservationList :List(Reservation) );
getReservationList @2 () -> ( reservationList :List(Reservation) );
} }
use @7 :Use; use @7 :Use;
@ -60,10 +62,16 @@ struct Machine {
interface InUse $CSharp.name("InUseInterface") { interface InUse $CSharp.name("InUseInterface") {
giveBack @0 (); giveBack @0 ();
sendRawData @1 (data :Data); sendRawData @1 (data :Data);
releasefortakeover @2 ();
} }
transfer @9 :Transfer; prodable @16 :Prodable;
interface Transfer $CSharp.name("TransferInterface") { interface Prodable $CSharp.name("ProdInterface") {
prodWithData @0 (data :Data);
}
takeover @9 :Takeover;
interface Takeover $CSharp.name("TakeoverInterface") {
accept @0 (); accept @0 ();
reject @1 (); reject @1 ();
} }
@ -76,16 +84,18 @@ struct Machine {
manage @11 :Manage; manage @11 :Manage;
interface Manage $CSharp.name("ManageInterface") { interface Manage $CSharp.name("ManageInterface") {
setProperty @0 (property :General.KeyValuePair); getMachineInfoExtended @0 () -> MachineInfoExtended;
removeProperty @1 (property :General.KeyValuePair);
setProperty @1 (property :General.KeyValuePair);
removeProperty @2 (property :General.KeyValuePair);
forceUse @2 (); forceUse @3 ();
forceFree @3 (); forceFree @4 ();
forceTransfer @4 (user :User); forceTransfer @5 (user :User);
block @5 (); block @6 ();
disabled @6 (); disabled @7 ();
} }
admin @12 :Admin; admin @12 :Admin;

View File

@ -7,15 +7,16 @@ using CSharp = import "programming_language/csharp.capnp";
$CSharp.namespace("FabAccessAPI.Schema"); $CSharp.namespace("FabAccessAPI.Schema");
using General = import "general.capnp"; using General = import "general.capnp";
using Optional = General.Optional;
using Machine = import "machine.capnp".Machine; using Machine = import "machine.capnp".Machine;
interface MachineSystem struct MachineSystem
{ {
info @0 () -> ( info : Info ); info @0 :Info;
interface Info $CSharp.name("InfoInterface") { interface Info $CSharp.name("InfoInterface") {
getMachineList @0 () -> ( machine_list :List(Machine) ); getMachineList @0 () -> ( machine_list :List(Machine) );
getMachine @1 ( id :Text ) -> ( machine :Machine, dummy :UInt8 = 0 ); getMachine @1 ( id :Text ) -> Optional(Machine);
getMachineURN @2 ( urn :Text ) -> ( machine :Machine, dummy :UInt8 = 0 ); getMachineURN @2 ( urn :Text ) -> Optional(Machine);
} }
} }

View File

@ -8,14 +8,14 @@ $CSharp.namespace("FabAccessAPI.Schema");
using Role = import "role.capnp".Role; using Role = import "role.capnp".Role;
interface PermissionSystem struct PermissionSystem
{ {
info @0 () -> ( info : Info ); info @0 :Info;
interface Info $CSharp.name("InfoInterface") { interface Info $CSharp.name("InfoInterface") {
getRoleList @0 () -> ( role_list :List(Role) ); getRoleList @0 () -> ( role_list :List(Role) );
} }
manage @1 () -> ( manage : Manage ); manage @1 :Manage;
interface Manage $CSharp.name("ManageInterface") { interface Manage $CSharp.name("ManageInterface") {
} }

View File

@ -24,8 +24,7 @@ struct User
info @3 :Info; info @3 :Info;
interface Info $CSharp.name("InfoInterface") { interface Info $CSharp.name("InfoInterface") {
getUserInfoExtended @0 () -> ( userInfoExtended :UserInfoExtended ); listRoles @0 () -> ( roles :List(Role) );
listRoles @1 () -> ( roles :List(Role) );
} }
manage @4 :Manage; manage @4 :Manage;
@ -35,61 +34,18 @@ struct User
admin @5 :Admin; admin @5 :Admin;
interface Admin $CSharp.name("AdminInterface") { interface Admin $CSharp.name("AdminInterface") {
addRole @0 ( role :Role ) -> (); getUserInfoExtended @0 () -> ( userInfoExtended :UserInfoExtended );
removeRole @1 ( role :Role ) -> ();
addRole @1 ( role :Role ) -> ();
removeRole @2 ( role :Role ) -> ();
pwd @2 ( new_pwd :Text ) -> (); pwd @3 ( new_pwd :Text ) -> ();
} }
cardDESFireEV2 @6 :CardDESFireEV2; cardDESFireEV2 @6 :CardDESFireEV2;
interface CardDESFireEV2 $CSharp.name("CardDESFireInterface") { interface CardDESFireEV2 $CSharp.name("CardDESFireInterface") {
# Card authentication using NXP/MiFare DESFire cards. # For more details about FabFire specification please see:
# These cards have the ability to restrict access for data on the cards using symmetric # https://docs.fab-access.org/books/fabfire-und-nfc-tags/page/fabfire-funktionsprinzip-grundlagen
# encryption and using a keyed Diffie-Hellman to prevent eavesdropping by any relaying
# party.
# A card has several "applications", containing up to 32 files. A file can be read or
# written. Both kinds of access can be restricted to parties knowing a PSK, on a
# file-to-file basis.
# The current system uses File 0001 through File 0004:
#
# File 0001 allows public (i.e. unauthenticated) read access and contains the Strings
# "FABACCESS", "DESFIRE", and "1.0" as packed list of UTF-8 encoded zero-terminated strings:
# (i.e. "FABACCESS\0DESFIRE\01.0\0")
# This file serves as sort of magic identifier allowing a server to verify quickly if it is
# able to use this card at all.
#
# File 0002 too allows public read access and contains:
# - An URL-encoded name of the issuing lab as URN in the format "urn:fabaccess:lab:<labname>"
# Examples:
# - "urn:fabaccess:lab:innovisionlab"
# - "urn:fabaccess:lab:Bibliothek%20Neustadt%20Makerspace"
# - "urn:fabaccess:lab:Offene%20Werkstatt%20M%C3%A4rz"
# - A valid IRI pointing towards the bffd instance running for this lab. This uffd SHOULD be
# reachable from the internet. Using private use IP addresses or IRIs that resolve to such
# may be necessary for labs behind restrictive firewalls or due to local policy.
# The IRI MUST use the "fabaccess" scheme, and SHOULD NOT contain an userinfo, path, query,
# or fragment part.
# Examples:
# - "fabaccess://innovisionlab.de/"
# - "fabaccess://192.168.178.65"
# - "fabaccess://fabaccess-server.localnet"
# - A zero-terminated list of UTF-8 encoded IRIs giving contact options to notify the issuer
# or owner in case the card has been lost. Issuers SHOULD set one value on card creation and
# MAY allow card owners to change or add values of their choosing.
# Examples:
# - "mailto:lostcard@innovisionlab.de"
# - "https://innovisionlab.de/lostcard"
# - "https://werkstatt-märz.de/cardlost.php?action=submitcardlost"
#
# File 0003 allows public access or access using a key, at the issuers option.
# It contains a token that can be used by the home server of the card owner to identify the
# card owner. The format of the token MUST NOT be relied on by any party except the home
# server.
#
# File 0004 restricts read access to a single key known to the home server of the card
# owner.
# It is empty but by being access restricted allows the home server to validate the card as
# being genuine and thus finalizing the authentication of the user.
getTokenList @0 () -> ( token_list :List(Data) ); getTokenList @0 () -> ( token_list :List(Data) );
# Get a list of all user Token currently bound to an user. This will generally be the number # Get a list of all user Token currently bound to an user. This will generally be the number
@ -117,4 +73,4 @@ struct User
# format to be written to the card as-is, but a client MAY add or change some information # format to be written to the card as-is, but a client MAY add or change some information
# contained. # contained.
} }
} }

View File

@ -8,19 +8,44 @@ $CSharp.namespace("FabAccessAPI.Schema");
using General = import "general.capnp"; using General = import "general.capnp";
using User = import "user.capnp".User; using User = import "user.capnp".User;
using Optional = General.Optional;
using Fallible = General.Fallible;
interface UserSystem struct UserSystem
{ {
info @0 () -> ( info : Info ); info @0 :Info;
interface Info $CSharp.name("InfoInterface") { interface Info $CSharp.name("InfoInterface") {
getUserSelf @0 ( ) -> ( user :User, dummy :UInt8 = 0 ); getUserSelf @0 ( ) -> User;
} }
manage @1 () -> ( manage : Manage ); search @2 :Search;
interface Search $CSharp.name("SearchInterface") {
getUserByName @0 (username: Text) -> Optional(User);
}
manage @1 :Manage;
interface Manage $CSharp.name("ManageInterface") { interface Manage $CSharp.name("ManageInterface") {
getUserList @0 () -> ( user_list :List(User) ); getUserList @0 () -> ( user_list :List(User) );
addUser @1 (username :Text, password: Text) -> ( user :User ); addUser @1 (username :Text, password: Text) -> User;
removeUser @2 (user :User, dummy :UInt8 = 0); # DEPRECATED: use `addUserFallible` instead
removeUser @2 (user: User);
struct AddUserError {
enum AddUserError $CSharp.name("AddUserErrorEnum") {
alreadyExists @0;
# An user with that username already exists
usernameInvalid @1;
# The provided username is unusable, e.g. contains invalid characters,
# is too long or too short.
passwordInvalid @2;
# The provided password is unusable, e.g. it's of zero length
}
error @0 :AddUserError;
}
addUserFallible @3 (username :Text, password: Text) -> Fallible(User, AddUserError);
} }
} }