import stampit from 'stampit';
import _ from 'lodash';
import {Meta, Model} from './base';
import {BaseQuerySet, Get, Create, BulkCreate, List, Delete} from '../querySet';
const UserQuerySet = stampit().compose(
BaseQuerySet,
Get,
Create,
Delete,
BulkCreate,
List
).methods({
/**
* Gets a user's groups.
* @memberOf UserQuerySet
* @instance
* @param {Object} properties lookup properties used for path resolving
* @returns {Promise}
* @example {@lang javascript}
* User.please().getGroups({id: 1, instanceName: 'test-one'}).then(function(groups) {});
*/
getGroups(properties = {}) {
const {Group} = this.getConfig();
this.properties = _.assign({}, this.properties, properties);
return Group.please().getUserGroups(this.properties);
},
/**
* Gets a user's group.
* @memberOf UserQuerySet
* @instance
* @param {Object} properties lookup properties used for path resolving
* @returns {Promise}
* @example {@lang javascript}
* User.please().getGroup({user: 1, instanceName: 'test-one', group: 1}).then(function(group) {});
*/
getGroup(properties = {}, group = {}) {
const {Group} = this.getConfig();
this.properties = _.assign({}, this.properties, properties);
return Group.please().getUserGroup(this.properties, group);
},
/**
* Adds a group to user.
* @memberOf UserQuerySet
* @instance
* @param {Object} properties lookup properties used for path resolving
* @param {Object} group object with id of group to be added
* @returns {Promise}
* @example {@lang javascript}
* User.please().getGroup({user: 1, instanceName: 'test-one'}, {group: 1}).then(function(group) {});
*/
addGroup(properties = {}, group = {}) {
const {Group} = this.getConfig();
this.properties = _.assign({}, this.properties, properties);
return Group.please().addUserGroup(this.properties, group);
},
/**
* Removes a user's group.
* @memberOf UserQuerySet
* @instance
* @param {Object} properties lookup properties used for path resolving
* @param {Object} group object with id of group to be added
* @returns {Promise}
* @example {@lang javascript}
* User.please().deleteGroup({user: 1, instanceName: 'test-one'}, {group: 1}).then(function(group) {});
*/
deleteGroup(properties = {}, group = {}) {
const {Group} = this.getConfig();
this.properties = _.assign({}, this.properties, properties);
return Group.please().deleteUserGroup(this.properties, group);
},
getDetails(properties = {}, user = {}) {
this.properties = _.assign({}, this.properties, properties, user);
this.method = 'GET';
this.endpoint = 'groupUser';
return this.then((response) => {
return this.model.fromJSON(response.user, this.properties);
});
},
groupUsers(properties = {}) {
this.properties = _.assign({}, this.properties, properties);
this.method = 'GET';
this.endpoint = 'groupUsers';
return this.then((response) => {
return this.model.please().asResultSet(response, 'user');
});
},
addUserToGroup(properties = {}, user = {}) {
this.properties = _.assign({}, this.properties, properties);
this.payload = user;
this.method = 'POST';
this.endpoint = 'groupUsers';
return this.then((response) => {
return this.model.fromJSON(response.user, this.properties);
});
},
deleteUserFromGroup(properties = {}, user = {}) {
this.properties = _.assign({}, this.properties, properties, user);
this.payload = user;
this.method = 'DELETE';
this.endpoint = 'groupUser';
return this;
},
get(properties = {}) {
const config = this.getConfig();
this.properties = _.assign({}, this.properties, properties);
this.method = 'GET';
this.endpoint = 'detail';
if (_.isEmpty(config.getAccountKey()) && !_.isEmpty(config.getUserKey()) && !_.isEmpty(config.getApiKey())) {
this.endpoint = 'user';
}
return this;
},
update(properties = {}, object = {}) {
const config = this.getConfig();
this.properties = _.assign({}, this.properties, properties);
this.payload = object;
this.method = 'PATCH';
this.endpoint = 'detail';
if (_.isEmpty(config.getAccountKey()) && !_.isEmpty(config.getUserKey()) && !_.isEmpty(config.getApiKey())) {
this.endpoint = 'user';
}
return this;
},
/**
* Restes user key.
* @memberOf UserQuerySet
* @instance
* @param {Object} properties lookup properties used for path resolving
* @returns {Promise}
* @example {@lang javascript}
* User.please().resetKey({id: 1, instanceName: 'test-one'}).then(function(user) {});
*/
resetKey(properties = {}) {
this.properties = _.assign({}, this.properties, properties);
this.method = 'POST';
this.endpoint = 'reset_key';
return this;
},
/**
* A convenience method for authenticating instance user with email and password.
* @memberOf UserQuerySet
* @instance
* @param {Object} properties
* @param {String} properties.instanceName
* @param {Object} credentials
* @param {String} credentials.email
* @param {String} credentials.password
* @returns {Promise}
*/
login(properties = {}, credentials = {}) {
const config = this.getConfig();
this.properties = _.assign({}, this.properties, properties);
this.method = 'POST';
this.endpoint = 'login';
this.payload = credentials;
return this.then((response) => {
config.setUserKey(response.user_key);
return this.model.fromJSON(response, this.properties);
});
},
/**
* A convenience method for authenticating instance user with email and password.
* @memberOf UserQuerySet
* @instance
* @param {Object} properties
* @param {String} properties.instanceName
* @param {String} properties.backend
* @param {Object} credentials
* @param {String} credentials.access_token
* @returns {Promise}
*/
socialLogin(properties = {}, credentials = {}) {
this.properties = _.assign({}, this.properties, properties);
this.method = 'POST';
this.endpoint = 'socialLogin';
this.payload = credentials;
return this;
}
});
const UserMeta = Meta({
name: 'user',
pluralName: 'users',
endpoints: {
'detail': {
'methods': ['delete', 'patch', 'put', 'get'],
'path': '/v1.1/instances/{instanceName}/users/{id}/'
},
'reset_key': {
'methods': ['post'],
'path': '/v1.1/instances/{instanceName}/users/{id}/reset_key/'
},
'list': {
'methods': ['post', 'get'],
'path': '/v1.1/instances/{instanceName}/users/'
},
'login': {
'methods': ['post'],
'path': '/v1.1/instances/{instanceName}/user/auth/'
},
'socialLogin': {
'methods': ['post'],
'path': '/v1.1/instances/{instanceName}/user/auth/{backend}/'
},
'user': {
'methods': ['get', 'post', 'patch'],
'path': '/v1.1/instances/{instanceName}/user/'
},
'groupUsers': {
'methods': ['get', 'post'],
'path': '/v1.1/instances/{instanceName}/groups/{id}/users/'
},
'groupUser': {
'methods': ['get', 'delete'],
'path': '/v1.1/instances/{instanceName}/groups/{id}/users/{user}/'
}
}
});
const UserConstraints = {
instanceName: {
presence: true,
length: {
minimum: 5
}
},
username: {
presence: true,
string: true
},
password: {
presence: true,
string: true
},
profile: {
object: true
},
'profile.owner_permissions': {
inclusion: ['none', 'read', 'write', 'full']
},
'profile.group': {
numericality: true
},
'profile.group_permissions': {
inclusion: ['none', 'read', 'write', 'full']
},
'profile.other_permissions': {
inclusion: ['none', 'read', 'write', 'full']
},
'profile.channel': {
string: true
},
'profile.channel_room': {
string: true
}
};
/**
* OO wrapper around instance users {@link http://docs.syncano.com/v4.0/docs/user-management endpoint}.
* @constructor
* @type {User}
* @property {Number} id
* @property {String} instanceName
* @property {String} username
* @property {String} password
* @property {String} user_key
* @property {String} [links = {}]
* @property {Date} [created_at = null]
* @property {Date} [updated_at = null]
*/
const User = stampit()
.compose(Model)
.setMeta(UserMeta)
.setQuerySet(UserQuerySet)
.setConstraints(UserConstraints)
.methods({
/**
* Gets a user's groups.
* @memberOf User
* @instance
* @returns {Promise}
* @example {@lang javascript}
* User.please().get({instanceName: 'test-one', id: 1}).then(function(user) {
* user.getGroups().then(function(groups) {});
* });
*/
getGroups() {
const {Group} = this.getConfig();
return Group.please().getUserGroups({ user: this.id, instanceName: this.instanceName});
},
/**
* Gets a user's group.
* @memberOf User
* @instance
* @returns {Promise}
* @example {@lang javascript}
* User.please().get({instanceName: 'test-one', id: 1}).then(function(user) {
* user.getGroup({ group: 1 }).then(function(group) {});
* });
*/
getGroup(group = {}) {
const {Group} = this.getConfig();
return Group.please().getUserGroup({ user: this.id, instanceName: this.instanceName}, group);
},
/**
* Adds a group to user.
* @memberOf User
* @instance
* @param {Object} group object with id of group to be added
* @returns {Promise}
* @example {@lang javascript}
* User.please().get({instanceName: 'test-one', id: 1}).then(function(user) {
* user.addGroup({ group: 1}).then(function(group) {});
* });
*/
addGroup(group = {}) {
const {Group} = this.getConfig();
return Group.please().addUserGroup({ user: this.id, instanceName: this.instanceName}, group);
},
/**
* Removes a user's group.
* @memberOf User
* @instance
* @param {Object} group object with id of group to be added
* @returns {Promise}
* @example {@lang javascript}
* User.please().get({instanceName: 'test-one', id: 1}).then(function(user) {
* user.deleteGroup({ group: 1}).then(function(group) {});
* });
*/
deleteGroup(group = {}) {
const {Group} = this.getConfig();
return Group.please().deleteUserGroup({ user: this.id, instanceName: this.instanceName}, group);
},
/**
* Restes user key.
* @memberOf User
* @instance
* @returns {Promise}
* @example {@lang javascript}
* User.please().get({instanceName: 'test-one', id: 1}).then(function(user) {
* user.resetKey().then(function(user) {});
* });
*/
resetKey() {
const meta = this.getMeta();
const path = meta.resolveEndpointPath('reset_key', this);
return this.makeRequest('POST', path, {}).then((body) => this.serialize(body));
}
});
export default User;