Skip to content
Permalink
Browse files

feat: add several features to identities, see summary (#12)

* feat: add identities.has()

* feat: add support for gender, nationality and address in the profile

* fix: forbid extraneous props in image

* feat: add identity.profile.setProperties()
  • Loading branch information...
satazor committed May 31, 2019
1 parent 343517c commit 2d2972c93d867dba2999ac2c01e1e8888c5a5270
Showing with 108 additions and 36 deletions.
  1. +29 −15 package-lock.json
  2. +1 −0 package.json
  3. +74 −21 src/identities/identity/profile.js
  4. +4 −0 src/identities/index.js

Some generated files are not rendered by default. Learn more.

@@ -104,6 +104,7 @@
"p-map": "^2.1.0",
"p-props": "^2.0.0",
"p-reduce": "^2.1.0",
"p-series": "^2.1.0",
"pico-signals": "^1.0.0",
"pify": "^4.0.1",
"scrypt-async": "^2.0.1",
@@ -1,5 +1,6 @@
import signal from 'pico-signals';
import pDelay from 'delay';
import pSeries from 'p-series';
import { pick, get, has, isPlainObject, isEqual } from 'lodash';
import {
InvalidProfilePropertyError,
@@ -46,25 +47,30 @@ class Profile {
async setProperty(key, value) {
assertProfileProperty(key, value);

if (PROFILE_BLOB_PROPERTIES.includes(key)) {
const blobRef = await this.#blobStore.put(key, value);
await this.#saveProperty(key, value);
}

value = pick(blobRef, 'type', 'hash');
}
async unsetProperty(key) {
assertProfilePropertyRemoval(key);

if (!isEqual(this.#orbitdbStore.get(key), value)) {
await this.#orbitdbStore.put(key, value);
}
await this.#removeProperty(key);
}

async unsetProperty(key) {
if (PROFILE_MANDATORY_PROPERTIES.includes(key)) {
throw new InvalidProfileUnsetPropertyError(key);
}
async setProperties(properties) {
const tasks = Object.entries(properties)
.map(([key, value]) => {
if (value === undefined) {
assertProfilePropertyRemoval(key);

if (has(this.#orbitdbStore.all, key)) {
await this.#orbitdbStore.del(key);
}
return () => this.#removeProperty(key);
}

assertProfileProperty(key, value);

return () => this.#saveProperty(key, value);
});

return pSeries(tasks);
}

getDetails() {
@@ -75,6 +81,24 @@ class Profile {
return this.#onChange.add(fn);
}

#saveProperty = async (key, value) => {
if (PROFILE_BLOB_PROPERTIES.includes(key)) {
const blobRef = await this.#blobStore.put(key, value);

value = pick(blobRef, 'type', 'hash');
}

if (!isEqual(this.#orbitdbStore.get(key), value)) {
await this.#orbitdbStore.put(key, value);
}
};

#removeProperty = async (key) => {
if (has(this.#orbitdbStore.all, key)) {
await this.#orbitdbStore.del(key);
}
};

#syncBlobStore = () => {
const blobRefs = pick(this.#orbitdbStore.all, PROFILE_BLOB_PROPERTIES);

@@ -174,17 +198,40 @@ const assertProfileProperty = (key, value) => {
if (!isPlainObject(value)) {
throw new InvalidProfilePropertyError(key, value);
}
if (typeof value.type !== 'string') {
throw new InvalidProfilePropertyError(`${key}.type`, value);

const { type, data, ...rest } = value;

if (typeof type !== 'string') {
throw new InvalidProfilePropertyError(`${key}.type`, type);
}

const typeParts = value.type.split('/');
const typeParts = type.split('/');

if (typeParts.length !== 2 || typeParts[0] !== 'image') {
throw new InvalidProfilePropertyError(`${key}.type`, value);
throw new InvalidProfilePropertyError(`${key}.type`, type);
}

if (!(data instanceof ArrayBuffer)) {
throw new InvalidProfilePropertyError(`${key}.data`, data);
}
if (!(value.data instanceof ArrayBuffer)) {
throw new InvalidProfilePropertyError(`${key}.data`, value);

const otherProps = Object.keys(rest);

if (otherProps.length) {
throw new UnsupportedProfilePropertyError(`${key}.${otherProps[0]}`);
}
break;
}
case 'gender': {
if (!['Male', 'Female', 'Other'].includes(value)) {
throw new InvalidProfilePropertyError(key, value);
}
break;
}
case 'nationality':
case 'address': {
if (typeof value !== 'string' || !value.trim()) {
throw new InvalidProfilePropertyError(key, value);
}
break;
}
@@ -193,11 +240,17 @@ const assertProfileProperty = (key, value) => {
}
};

const assertProfilePropertyRemoval = (key) => {
if (PROFILE_MANDATORY_PROPERTIES.includes(key)) {
throw new InvalidProfileUnsetPropertyError(key);
}
};

export const assertProfileDetails = (details) => {
PROFILE_MANDATORY_PROPERTIES.forEach((property) => {
const value = details && details[property];

if (value == null) {
if (value === undefined) {
throw new InvalidProfilePropertyError(property, value);
}
});
@@ -45,6 +45,10 @@ class Identities {
return this.#identitiesList;
}

has(id) {
return Boolean(this.#identitiesMap[id]);
}

get(id) {
if (!this.#identitiesMap) {
throw new IdentitiesNotLoadedError();

0 comments on commit 2d2972c

Please sign in to comment.
You can’t perform that action at this time.