Exemplo n.º 1
0
        internal LogEntry Wrap <T>(T model) where T : ILogSerialized
        {
            var type    = _typeProvider.Get(typeof(Page)).GetValueOrDefault();
            var version = LogSerializeContext.FormatVersion;

            var @object = new LogObject
            {
                Timestamp = TimestampFactory.Now,
                Type      = type,
                Version   = version,
                Data      = model
            };

            @object.Hash = _hashProvider.ComputeHashBytes(@object);

            // FIXME: inefficient, cache the last value somewhere?
            var previousHash = new byte[0];

            foreach (var item in _store.StreamEntries())
            {
                previousHash = item.Hash;
            }

            var entry = new LogEntry
            {
                PreviousHash = previousHash,
                Timestamp    = @object.Timestamp,
                Nonce        = Crypto.Nonce(64U),
                Objects      = new[] { @object }
            };

            entry.HashRoot = _hashProvider.ComputeHashRootBytes(entry);
            entry.Hash     = _hashProvider.ComputeHashBytes(entry);

            return(entry);
        }
Exemplo n.º 2
0
        public async Task MaterializeAsync(ILogStore store, byte[] secretKey   = default, long?startingFrom = default,
                                           CancellationToken cancellationToken = default)
        {
            if (startingFrom == default)
            {
                startingFrom = Interlocked.Read(ref _index) + 1;
            }

            foreach (var entry in store.StreamEntries((ulong)startingFrom, secretKey))
            {
                Interlocked.Exchange(ref _index, (long)entry.Index.GetValueOrDefault());

                foreach (var @object in entry.Objects)
                {
                    switch (@object.Data)
                    {
                    case Namespace ns:
                    {
                        var key = ns;
                        Namespaces.Add(key);
                        _namespace = key;

                        if (!Revisions.ContainsKey(_namespace.Value))
                        {
                            Revisions.Add(_namespace.Value,
                                          new Dictionary <string, ulong>(StringComparer.OrdinalIgnoreCase));
                        }

                        if (!Manifest.ContainsKey(_namespace.Value))
                        {
                            Manifest.Add(_namespace.Value, new Dictionary <ulong, List <Schema> >());
                        }

                        if (!Roles.ContainsKey(_namespace.Value))
                        {
                            Roles.Add(_namespace.Value, new List <string>());
                        }

                        break;
                    }

                    case Schema schema:
                    {
                        var key = schema.Name;

                        if (!Revisions[_namespace.Value].TryGetValue(key, out var revision))
                        {
                            Revisions[_namespace.Value].Add(key, revision = 1);
                        }

                        if (!Manifest[_namespace.Value].TryGetValue(revision, out var manifest))
                        {
                            Manifest[_namespace.Value].Add(revision, manifest = new List <Schema>());
                        }

                        if (!Schemas.TryGetValue(key, out var schemaMap))
                        {
                            Schemas.Add(key, schemaMap = new Dictionary <ulong, List <Schema> >());
                        }

                        if (!schemaMap.TryGetValue(revision, out var list))
                        {
                            schemaMap.Add(revision, list = new List <Schema>());
                        }

                        manifest.Add(schema);
                        list.Add(schema);

                        await _events.OnSchemaAddedAsync(store, schema, cancellationToken);

                        break;
                    }

                    case RevokeRole revokeRole:
                    {
                        if (!revokeRole.Verify())
                        {
                            throw new InvalidOperationException($"invalid {revokeRole.Type}");
                        }

                        if (RoleGrants.TryGetValue(_namespace.Value, out var lookup) &&
                            lookup.Count == 1 &&
                            lookup[Constants.DefaultOwnerRole].Count == 1)
                        {
                            throw new CannotRemoveSingleOwnerException("cannot revoke admin rights of only owner");
                        }

                        break;
                    }

                    default:
                        throw new NotImplementedException(@object.Data.GetType().Name);
                    }
                }
            }
        }