Skip to content

Commit

Permalink
a number of improvements/updates tot he data returned by invite endpo…
Browse files Browse the repository at this point in the history
…ints to be consisten (rust tends to get very whiny when the required fields dont show up, which is FINE but we need to be consistent). also, adding some functions for getting the profile size, and implementing in the GET /users/<userid> endpoint generally called ONCE post-login. so far so good. for now only takes note data/file data into account. seems like a good bet. i guess it would be possible to store gigabytes of data in a board or space title, but we will cross that bridge when some clever jerk discovers THIS ONE SIMPLE TRICK THAT HAS DEVELOPERS FURIOUS
  • Loading branch information
orthecreedence committed Sep 10, 2017
1 parent bf57f9c commit 054c4b6
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 22 deletions.
2 changes: 2 additions & 0 deletions TODO
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
- calculate storage (see user model)
- on space delete, delete keychain entries for that space

17 changes: 16 additions & 1 deletion controllers/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ var tres = require('../helpers/tres');
var config = require('../helpers/config');
var log = require('../helpers/log');
var analytics = require('../models/analytics');
var profile_model = require('../models/profile');

exports.route = function(app) {
app.post('/users', join);
Expand All @@ -13,6 +14,7 @@ exports.route = function(app) {
app.delete('/users/:user_id', delete_account);
app.post('/users/confirmation/resend', resend_confirmation);
app.put('/users/:user_id', update_user);
app.get('/users/:user_id/profile-size', get_profile_size);
};

/**
Expand All @@ -34,7 +36,7 @@ var get_by_id = function(req, res) {
if(user_id != cur_user_id) {
return tres.err(res, new Error('you can\'t grab another user\'s info'));
}
tres.wrap(res, model.get_by_id(user_id, {data: true}));
tres.wrap(res, model.get_by_id(user_id, {data: true, profile_size: true}));
};

var get_by_email = function(req, res) {
Expand Down Expand Up @@ -97,3 +99,16 @@ var update_user = function(req, res) {
tres.wrap(res, model.update(cur_user_id, user_id, data));
};

/**
* grab the current user's profile size in bytes, along with their usage
* percentage
*/
var get_profile_size = function(req, res) {
var cur_user_id = req.user.id;
var user_id = req.params.user_id;
if(user_id != cur_user_id) {
return tres.err(res, new Error('you can\'t get another user\'s profile data'));
}
tres.wrap(res, profile_model.get_profile_size(cur_user_id));
};

14 changes: 9 additions & 5 deletions models/invite.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,12 @@ exports.accept = function(user_id, space_id, invite_id, post_accept_fn) {
return delete_invite(space_id, invite_id);
})
.then(function(invite) {
return space_model.get_by_id(space_id)
return space_model.get_by_id(space_id, {populate: true})
})
.then(function(space) {
var space = space.data;
return space_model.get_space_user_ids(space_id)
.then(function(space_users) {
.tap(function(space_users) {
return Promise.all([
sync_model.add_record([user_id], user_id, 'space', space_id, 'share'),
sync_model.add_record([user_id], user_id, 'invite', invite_id, 'delete'),
Expand All @@ -212,7 +213,7 @@ exports.accept = function(user_id, space_id, invite_id, post_accept_fn) {
return space;
});
})
.tap(function(invite) {
.tap(function(_invite) {
if(post_accept_fn) post_accept_fn(invite);
return {accepted: true};
});
Expand All @@ -231,8 +232,11 @@ exports.update = function(user_id, space_id, invite_id, data) {
data: invite_data
};
return db.update('spaces_invites', invite_id, update)
.then(function(item) {
var inv = item.data;
.then(function() {
return link([invite_id])
.then(function(invites) { return invites[0]; });
})
.then(function(inv) {
return space_model.get_space_user_ids(space_id)
.then(function(user_ids) {
// do an "edit" sync on the space, not the invite.
Expand Down
17 changes: 17 additions & 0 deletions models/profile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
var error = require('../helpers/error');
var space_model = require('./space');

exports.get_profile_size = function(user_id) {
// grab the user's owned spaces
return space_model.get_by_user_id(user_id, {role: space_model.roles.owner})
.then(function(owned_spaces) {
// grab the size for each space
return Promise.all(owned_spaces.map(function(space) {
return space_model.get_space_size(space.id);
}));
})
.then(function(space_sizes) {
return space_sizes.reduce(function(acc, x) { return acc + x; }, 0);
});
};

68 changes: 63 additions & 5 deletions models/space.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,12 @@ var populate_members = function(spaces, options) {
.then(function(users) {
var user_idx = {};
users.forEach(function(u) { user_idx[u.id] = u; });

members.forEach(function(member) {
// filter our members that don't exist anymore
members = members.filter(function(member) {
var user = user_idx[member.user_id];
if(!user) return;
if(!user) return false;
member.username = user.username;
return true;
});
return members;
});
Expand Down Expand Up @@ -154,10 +155,15 @@ var get_by_id = function(space_id, options) {
return db.by_id('spaces', space_id)
.then(function(space) {
if(!space) return false;
if(options.populate) {
return populate_members([space])
.then(function(spaces) { return spaces[0]; });
}
if(options.raw) return space;
return space.data;
});
};
exports.get_by_id = get_by_id;

/**
* given a space id, pull out all user_ids accociated with the spaces.
Expand Down Expand Up @@ -224,6 +230,14 @@ var get_space_user_record = function(user_id, space_id) {
return db.first(qry, {space_id: space_id, user_id: user_id});
};

/**
* Get all invite records for this space
*/
var get_space_invites = function(space_id) {
var qry = 'SELECT * FROM spaces_invites WHERE space_id = {{space_id}}';
return db.query(qry, {space_id: space_id});
};

/**
* get the data tree for a space (all the boards/notes/invites contained in it).
*/
Expand All @@ -245,7 +259,7 @@ exports.get_data_tree = function(space_id, options) {
return populate_members([space], options);
})
.then(function(spaces) {
return spaces[0].data;
return spaces && spaces[0].data;
});
return Promise.all([
space_promise,
Expand Down Expand Up @@ -273,6 +287,12 @@ exports.update_member = function(user_id, space_id, member_user_id, data) {
}
return db.update('spaces_users', member.id, data);
})
.tap(function(member) {
return user_model.get_by_id(member.user_id)
.then(function(user) {
member.username = user.username;
});
})
.tap(function() {
return exports.get_space_user_ids(space_id)
.then(function(user_ids) {
Expand Down Expand Up @@ -427,6 +447,23 @@ var del = function(user_id, space_id) {
}, {concurrency: 8});
return Promise.all([note_delete, board_delete]);
})
.then(function() {
// build/save sync records for all our deleted invites
var inv_map = {};
return get_space_invites(space_id)
.then(function(invites) {
let usernames = invites.map(function(i) {
inv_map[i.to_user] = i;
return i.to_user;
});
return user_model.get_by_emails(usernames);
})
.then(function(users) {
return Promise.all(users.map(function(u) {
return sync_model.add_record([u.id], user_id, 'invite', inv_map[u.username].id, 'delete');
}));
});
})
.then(function() {
var params = {space_id: space_id};
return Promise.all([
Expand Down Expand Up @@ -614,7 +651,28 @@ exports.simple_move_space = function(sync_type, sync_table, perms_delete, perms_
return {data: item, sync_ids: []};
});
};
}
};

/**
* Gets the size of a space in bytes (includes note content and files).
*/
exports.get_space_size = function(space_id) {
var qry = [
'SELECT',
' OCTET_LENGTH(n.data->>\'body\') AS nsize,',
' (data#>>\'{file,size}\')::int AS fsize',
'FROM',
' notes n',
'WHERE',
' space_id = {{space_id}}',
];
return db.query(qry.join('\n'), {space_id: space_id})
.then(function(notes) {
return notes.reduce(function(acc, x) {
return acc + parseInt(x.nsize || 0) + parseInt(x.fsize || 0);
}, 0);
});
};

sync_model.register('space', {
'add': add,
Expand Down
31 changes: 22 additions & 9 deletions models/sync.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ var make_sync_record = function(user_id, item_type, item_id, action) {
* Given an item that can be synced, convert it into a sync record.
*/
var convert_to_sync = function(item, type, action) {
var sync = make_sync_record(item.user_id, type, item.id, action);
var user_id = item.user_id;
if(!user_id && type == 'invite') user_id = item.from_user_id;
var sync = make_sync_record(user_id, type, item.id, action);
if(action == 'delete') {
sync.data = {id: item.id, deleted: true};
} else {
Expand Down Expand Up @@ -246,15 +248,26 @@ var populate_shares = function(user_id, sync_records) {
return space_model.get_data_tree(sync.item_id, {skip_invites: !has_perm});
})
.spread(function(space, boards, notes) {
populated.push(convert_to_sync(space, 'space', action));
boards.forEach(function(item) {
var sync = convert_to_sync(item, 'board', action);
// make sure the space actually exists before creating our
// sync records. otherwise, we just pass through the
// original sync record, but with our add/delete action
// (and we'll have {missing: true} for our `data` tee hee)
if(space) {
populated.push(convert_to_sync(space, 'space', action));
boards.forEach(function(item) {
var sync = convert_to_sync(item, 'board', action);
populated.push(sync);
});
notes.forEach(function(item) {
var sync = convert_to_sync(item, 'note', action);
populated.push(sync);
});
} else {
// ah ah! alex, remember what we talked about? mmhmm
// thank you. shutup. thank you.
sync.action = action;
populated.push(sync);
});
notes.forEach(function(item) {
var sync = convert_to_sync(item, 'note', action);
populated.push(sync);
});
}
});
} else {
populated.push(sync);
Expand Down
17 changes: 15 additions & 2 deletions models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ var invite_model = require('./invite');
var keychain_model = require('./keychain');
var analytics = require('./analytics');
var email_model = require('./email');
var profile_model = require('./profile');

vlad.define('user', {
username: {type: vlad.type.email},
Expand Down Expand Up @@ -366,10 +367,21 @@ exports.get_by_ids = function(user_ids, options) {
options || (options = {});
return db.by_ids('users', user_ids)
.each(clean_user)
.map(function(user) {
if(options.profile_size) {
return profile_model.get_profile_size(user.id)
.then(function(size) {
user.profile_size = size;
return user;
});
} else {
return user;
}
})
.map(function(user) {
if(!options.data) return user;
var data = user.data;
['id', 'username', 'storage_mb', 'confirmed'].forEach(function(field) {
['id', 'username', 'storage_mb', 'confirmed', 'profile_size'].forEach(function(field) {
data[field] = user[field];
});
return data;
Expand Down Expand Up @@ -400,7 +412,8 @@ exports.get_by_email = function(email, options) {
});
};

exports.calculate_storage = function(user_id) {
exports.get_by_emails = function(emails) {
return db.by_ids('users', emails, {id_field: 'username'})
};

var edit = function(user_id, data) {
Expand Down

0 comments on commit 054c4b6

Please sign in to comment.