nuts-foundation/nuts-node

View on GitHub
vcr/credential/revocation.go

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
/*
 * Nuts node
 * Copyright (C) 2021 Nuts community
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

package credential

import (
    "fmt"
    "time"

    ssi "github.com/nuts-foundation/go-did"
    "github.com/nuts-foundation/go-did/vc"
)

// Revocation defines a proof that a VC has been revoked by its issuer.
type Revocation struct {
    // Context contains the json-ld contexts
    Context []ssi.URI `json:"@context,omitempty"`
    // Type contains the json-ld type, usually this is CredentialRevocation
    Type []ssi.URI `json:"type,omitempty"`
    // Issuer refers to the party that issued the credential
    Issuer ssi.URI `json:"issuer"`
    // Subject refers to the VC that is revoked
    Subject ssi.URI `json:"subject"`
    // Reason describes why the VC has been revoked
    Reason string `json:"reason,omitempty"`
    // Date is a rfc3339 formatted datetime.
    Date time.Time `json:"date"`
    // Proof contains the cryptographic proof(s). It must be extracted using the Proofs method or UnmarshalProofValue method for non-generic proof fields.
    Proof *vc.JSONWebSignature2020Proof `json:"proof,omitempty"`
}

// nowFunc is used to store a function that returns the current time. This can be changed when you want to mock the current time.
var nowFunc = time.Now

// RevocationType contains the JSON-LD type for a revocation
var RevocationType = ssi.MustParseURI("CredentialRevocation")

// BuildRevocation generates a revocation based on the credential
func BuildRevocation(issuer ssi.URI, subject ssi.URI) Revocation {
    nutsCredentialContext := ssi.MustParseURI("https://nuts.nl/credentials/v1")
    return Revocation{
        Context: []ssi.URI{nutsCredentialContext},
        Type:    []ssi.URI{RevocationType},
        Issuer:  issuer,
        Subject: subject,
        Date:    nowFunc(),
    }
}

// ValidateRevocation checks if a revocation record contains the required fields and if fields have the correct value.
func ValidateRevocation(r Revocation) error {
    if r.Subject.String() == "" || r.Subject.Fragment == "" {
        return fmt.Errorf("%w: 'subject' is required and requires a valid fragment", errValidation)
    }

    // Only check type if @context is set
    if len(r.Context) != 0 {
        foundType := false
        for _, val := range r.Type {
            if val == RevocationType {
                foundType = true
                break
            }
        }
        if !foundType {
            return fmt.Errorf("%w: 'type' does not contain %s", errValidation, RevocationType)
        }
    }

    if r.Issuer.String() == "" {
        return fmt.Errorf("%w: 'issuer' is required", errValidation)
    }

    if r.Date.IsZero() {
        return fmt.Errorf("%w: 'date' is required", errValidation)
    }

    if r.Proof == nil {
        return fmt.Errorf("%w: 'proof' is required", errValidation)
    }

    return nil
}