mirror of
https://github.com/diaspora/diaspora.git
synced 2026-01-13 00:57:58 -05:00
Compare commits
1132 Commits
last-mongo
...
last-data-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
adbd23ec50 | ||
|
|
28fc093a01 | ||
|
|
01e3b3cc26 | ||
|
|
d91fda656c | ||
|
|
e8bb4c2d66 | ||
|
|
03f90a999d | ||
|
|
1d6a69ea82 | ||
|
|
1702081af7 | ||
|
|
a544a189ff | ||
|
|
2a5d41cc82 | ||
|
|
5cae971ba1 | ||
|
|
6ba0083337 | ||
|
|
6af21e00ca | ||
|
|
fb6e32e3bf | ||
|
|
63caff1f40 | ||
|
|
67affa2f5f | ||
|
|
7c3a173010 | ||
|
|
ed8d4db3a8 | ||
|
|
e52d14f1e9 | ||
|
|
ab997e2d21 | ||
|
|
59820d1994 | ||
|
|
fd6545b609 | ||
|
|
2d5dc81854 | ||
|
|
0745a5ed7c | ||
|
|
50d9d76562 | ||
|
|
1c94600b66 | ||
|
|
b7eec2e843 | ||
|
|
00b0edcd39 | ||
|
|
d825eeaaa0 | ||
|
|
580f0576c8 | ||
|
|
52b970098b | ||
|
|
e9a843b095 | ||
|
|
155290fb51 | ||
|
|
5582c2b5f3 | ||
|
|
0c31cc4259 | ||
|
|
98633658f4 | ||
|
|
70e4a671a2 | ||
|
|
20d40b7440 | ||
|
|
c256533a2f | ||
|
|
2ff4af6800 | ||
|
|
7ac3692a92 | ||
|
|
8f1a6f502e | ||
|
|
6e78d6f6c5 | ||
|
|
9f368bf82f | ||
|
|
fbfd46a506 | ||
|
|
879672576f | ||
|
|
b93084e04f | ||
|
|
e3c5e7ba05 | ||
|
|
c502e4591a | ||
|
|
e4be5db881 | ||
|
|
14033e7b5f | ||
|
|
e2903a1251 | ||
|
|
189b7fb5ac | ||
|
|
2b38fe820f | ||
|
|
cdab6a1a84 | ||
|
|
a80179e77f | ||
|
|
29d23d9f43 | ||
|
|
5748639c08 | ||
|
|
c7362707b3 | ||
|
|
ead1f80b08 | ||
|
|
d448436376 | ||
|
|
b50217c98c | ||
|
|
ffa6b9879f | ||
|
|
35cabd469f | ||
|
|
9b00b2c786 | ||
|
|
54130b49b7 | ||
|
|
9ad96726de | ||
|
|
004d9b5028 | ||
|
|
490a2c6a9e | ||
|
|
35903514f5 | ||
|
|
b86098055e | ||
|
|
c35f143b29 | ||
|
|
ea98b1ca81 | ||
|
|
f19857cc40 | ||
|
|
c1bcfef90c | ||
|
|
10345b14a8 | ||
|
|
c9545920f8 | ||
|
|
214c677169 | ||
|
|
d7c7775b6c | ||
|
|
93bdf1e91e | ||
|
|
2cf0503310 | ||
|
|
05f9d79689 | ||
|
|
1f3261b2ef | ||
|
|
8f929d2b85 | ||
|
|
9d1bb3ac21 | ||
|
|
2b6070d325 | ||
|
|
8837632dd9 | ||
|
|
8c5621158d | ||
|
|
0416fa14b2 | ||
|
|
8a419a84a6 | ||
|
|
ddbd5febb3 | ||
|
|
7b0a354677 | ||
|
|
dd97f1b985 | ||
|
|
58796dcde2 | ||
|
|
7bf256ecfa | ||
|
|
6d314e9394 | ||
|
|
1e3533b1b1 | ||
|
|
1baafac84b | ||
|
|
90aac1d175 | ||
|
|
af43a60b62 | ||
|
|
9324aceefc | ||
|
|
337831bba2 | ||
|
|
584684560e | ||
|
|
e6836c46a7 | ||
|
|
f2cc51dd0d | ||
|
|
5b73e9ca06 | ||
|
|
1ac688f82c | ||
|
|
9d480b0961 | ||
|
|
f9279f9bbc | ||
|
|
eafa965504 | ||
|
|
3f5844aaa0 | ||
|
|
5cc7aa4496 | ||
|
|
e38a136c49 | ||
|
|
3c4ec6d39d | ||
|
|
cf93bfc89b | ||
|
|
f8c0906db7 | ||
|
|
dc7a672d9f | ||
|
|
ee6932a3f7 | ||
|
|
d0569fb881 | ||
|
|
c259fc65f0 | ||
|
|
deeb8044f5 | ||
|
|
b21ea3c85a | ||
|
|
ef58c5f13d | ||
|
|
a5d170ef1c | ||
|
|
5631e45b6d | ||
|
|
0d1133cd51 | ||
|
|
c697df4b5a | ||
|
|
dda477410d | ||
|
|
1f5edb1d92 | ||
|
|
81f0cd7f07 | ||
|
|
ac738df8f5 | ||
|
|
c252cfa025 | ||
|
|
d38e3a6b29 | ||
|
|
84198e4750 | ||
|
|
9490538e44 | ||
|
|
5f841b9add | ||
|
|
78e30ff459 | ||
|
|
7b5b980095 | ||
|
|
8bcf1b49c7 | ||
|
|
fd0bc8a09a | ||
|
|
fb5e5cc341 | ||
|
|
fca5310c77 | ||
|
|
b7c3f93d25 | ||
|
|
97aff09140 | ||
|
|
6e7bdf7cad | ||
|
|
8c1cb0d6e8 | ||
|
|
a45f46828a | ||
|
|
909a198380 | ||
|
|
80a3a3446a | ||
|
|
e537104fb4 | ||
|
|
e00a033e9e | ||
|
|
981c37d286 | ||
|
|
c79b55f520 | ||
|
|
8fafc48d32 | ||
|
|
d50863cc90 | ||
|
|
48fff29bf6 | ||
|
|
a865373bfa | ||
|
|
06ff32d8d5 | ||
|
|
5f55dfa1bc | ||
|
|
eb9705c82d | ||
|
|
435451bc5b | ||
|
|
f0ba62be59 | ||
|
|
ae0595bca8 | ||
|
|
3d0831f2b2 | ||
|
|
da12954d22 | ||
|
|
2522ab7ee4 | ||
|
|
8ab54076f8 | ||
|
|
1afc83f356 | ||
|
|
685130cbd4 | ||
|
|
9d7611f8d8 | ||
|
|
770091e82b | ||
|
|
8ee81314d6 | ||
|
|
9d92161430 | ||
|
|
f58c477673 | ||
|
|
ba6afa50e8 | ||
|
|
1590b69569 | ||
|
|
d183150fa9 | ||
|
|
3812612c86 | ||
|
|
68f0f7ec21 | ||
|
|
21fd546cd0 | ||
|
|
0cb218bba0 | ||
|
|
11309574cf | ||
|
|
c62e9db397 | ||
|
|
f4e6d0d82b | ||
|
|
bd908a9b95 | ||
|
|
1072806d8f | ||
|
|
a179bac689 | ||
|
|
979d9d7fb4 | ||
|
|
090c412690 | ||
|
|
c5801ffb37 | ||
|
|
9fe0320881 | ||
|
|
a7f149e399 | ||
|
|
00cca370ad | ||
|
|
1c1fba63e7 | ||
|
|
809ee8a678 | ||
|
|
00ebf6469b | ||
|
|
31f5500b11 | ||
|
|
ac2c50b33f | ||
|
|
ebfebb16d7 | ||
|
|
a11507d30c | ||
|
|
a0a901a675 | ||
|
|
810220bc97 | ||
|
|
98d8d9e0da | ||
|
|
d8956a7cd5 | ||
|
|
98999b1703 | ||
|
|
8a4ca3af0e | ||
|
|
1bfbb4b605 | ||
|
|
208a47162c | ||
|
|
b6dc32959c | ||
|
|
43e10307a6 | ||
|
|
5e69f7d9a2 | ||
|
|
f28a6a9f80 | ||
|
|
0fc5f1c043 | ||
|
|
1adcc4cc99 | ||
|
|
b47714f881 | ||
|
|
5bcc3acbbb | ||
|
|
cd8deca4bb | ||
|
|
a42c1225d1 | ||
|
|
1832743e5f | ||
|
|
afecfe5e93 | ||
|
|
782dc55d63 | ||
|
|
a9ab842242 | ||
|
|
c1e679ff8d | ||
|
|
e6f11a39b5 | ||
|
|
3538bda06d | ||
|
|
b95c9b2e66 | ||
|
|
c9af2e87aa | ||
|
|
22d83ec502 | ||
|
|
f3202e15d6 | ||
|
|
c5e0bc40bb | ||
|
|
ee96dea398 | ||
|
|
d8d89cb6c2 | ||
|
|
62b164458b | ||
|
|
7693c162c2 | ||
|
|
9fdf1e599f | ||
|
|
d4fb1d8af6 | ||
|
|
40fa91ead9 | ||
|
|
83576d75ef | ||
|
|
c27e2de478 | ||
|
|
ec93faa2c4 | ||
|
|
adfcc59631 | ||
|
|
e61cc2fd34 | ||
|
|
126925f28f | ||
|
|
78b242b110 | ||
|
|
50cd06129a | ||
|
|
c030e8b21e | ||
|
|
40dea1f625 | ||
|
|
126a4b2547 | ||
|
|
736783abd7 | ||
|
|
22c4ebd6de | ||
|
|
ff796efce0 | ||
|
|
62badaa0df | ||
|
|
e964490a9a | ||
|
|
faf026dec6 | ||
|
|
69a98a2f5a | ||
|
|
2c5fc1bdd9 | ||
|
|
d75bc10ac0 | ||
|
|
936b997dff | ||
|
|
bb5d5fc2c0 | ||
|
|
638311125f | ||
|
|
c9dd2d5b50 | ||
|
|
8f6922bcf9 | ||
|
|
ea6dc0eb9a | ||
|
|
d32fe1ea08 | ||
|
|
98cdee97c0 | ||
|
|
e106ec6a79 | ||
|
|
97e00f9ee3 | ||
|
|
16e8ecc72c | ||
|
|
e446dcaeb5 | ||
|
|
5bce2d1615 | ||
|
|
ec21230756 | ||
|
|
e4ba498d70 | ||
|
|
f41bc0c14d | ||
|
|
06a992a088 | ||
|
|
74b8921c09 | ||
|
|
17f41f1291 | ||
|
|
efd95df029 | ||
|
|
15a1eb8afc | ||
|
|
eb9a943724 | ||
|
|
801382714a | ||
|
|
9ef6606f80 | ||
|
|
e943d6ae5e | ||
|
|
3d034668fd | ||
|
|
85c346b520 | ||
|
|
65447e63ec | ||
|
|
e04685e7ab | ||
|
|
33c7400919 | ||
|
|
dcf7e57a1d | ||
|
|
814ef38fa9 | ||
|
|
feb47df97e | ||
|
|
e02c3eafc0 | ||
|
|
e4ae0ddf67 | ||
|
|
49adf5034f | ||
|
|
fe3c67a662 | ||
|
|
26779889d0 | ||
|
|
3d6d742def | ||
|
|
166f75d883 | ||
|
|
da244f8438 | ||
|
|
ab706f4127 | ||
|
|
abf385d79d | ||
|
|
5ac91d771a | ||
|
|
77cac72ed5 | ||
|
|
47d2b752c2 | ||
|
|
2b625c468a | ||
|
|
af14fa76a1 | ||
|
|
183c840108 | ||
|
|
8c1fc12d82 | ||
|
|
ad141bc5a2 | ||
|
|
ee8796fc79 | ||
|
|
dc499293b3 | ||
|
|
b7815f0d84 | ||
|
|
ea3b719253 | ||
|
|
5a23907143 | ||
|
|
b0d98b9ce8 | ||
|
|
77adc02cbd | ||
|
|
51df11aafc | ||
|
|
edf15aa5bd | ||
|
|
11a4544882 | ||
|
|
3a26673298 | ||
|
|
aa6ac41d68 | ||
|
|
7ab287c3e1 | ||
|
|
dcaa84f73d | ||
|
|
17c3f0a0ee | ||
|
|
11f95ee596 | ||
|
|
02f7f10ef1 | ||
|
|
a13a7ad5c1 | ||
|
|
17daf3c7ca | ||
|
|
096e5e577b | ||
|
|
124ac738ea | ||
|
|
778afa2889 | ||
|
|
199d5fbdc1 | ||
|
|
61dd5a835a | ||
|
|
43f17b3ed8 | ||
|
|
3c8a87783f | ||
|
|
37a699ace1 | ||
|
|
6dc35c516a | ||
|
|
a1fdd3cdf9 | ||
|
|
585ca4820b | ||
|
|
0bf3cae54a | ||
|
|
c3e101112d | ||
|
|
ece7cddc51 | ||
|
|
05a7b88899 | ||
|
|
666c040c1d | ||
|
|
5823da8d25 | ||
|
|
cc84e349de | ||
|
|
e3b298c5d4 | ||
|
|
2540c5adb9 | ||
|
|
8196ee33dd | ||
|
|
23754ec3fb | ||
|
|
a68dfbcabc | ||
|
|
16b7ec3990 | ||
|
|
25671f07c7 | ||
|
|
ba779e18d6 | ||
|
|
1e6bf9c80e | ||
|
|
7ace73b84b | ||
|
|
8c2e6dd8cb | ||
|
|
c6eb5d0340 | ||
|
|
8ae23f5705 | ||
|
|
17a801394e | ||
|
|
6858e2e543 | ||
|
|
2304827569 | ||
|
|
fc9d9a4c55 | ||
|
|
51bc26c3df | ||
|
|
2394d40603 | ||
|
|
edef56c84a | ||
|
|
026ced5276 | ||
|
|
b7ce51d206 | ||
|
|
dc74aed79b | ||
|
|
ef9ab553bf | ||
|
|
ff4a049d2d | ||
|
|
cd7e4d6e8f | ||
|
|
6cf8de94a7 | ||
|
|
11e431f640 | ||
|
|
dfa5d875c5 | ||
|
|
a636ceec7f | ||
|
|
2161c1dd72 | ||
|
|
41f077e039 | ||
|
|
e2ec4c0424 | ||
|
|
90897099bd | ||
|
|
d1b91e1eac | ||
|
|
151b23f77b | ||
|
|
e3df222d0e | ||
|
|
f7de3a216a | ||
|
|
7fb6c5bcb9 | ||
|
|
ba439b9413 | ||
|
|
2b3926c629 | ||
|
|
42fd9a19da | ||
|
|
7f4e048cad | ||
|
|
54feaca998 | ||
|
|
b4b3fd2bb3 | ||
|
|
fbaf9d6e84 | ||
|
|
4111a0ae4e | ||
|
|
614aa3056a | ||
|
|
164fe1c1b5 | ||
|
|
50ea657cd2 | ||
|
|
9f78156206 | ||
|
|
965f4e2ea5 | ||
|
|
20e1316491 | ||
|
|
86cc7a0d35 | ||
|
|
654be58a87 | ||
|
|
81369176f1 | ||
|
|
935b934b7a | ||
|
|
ca0d52c8e2 | ||
|
|
cac8c586de | ||
|
|
8fabe0f402 | ||
|
|
753a113aa9 | ||
|
|
9b88eef832 | ||
|
|
2dcbb9bb12 | ||
|
|
1a4f580716 | ||
|
|
10805c1187 | ||
|
|
166039f37a | ||
|
|
d030343048 | ||
|
|
6df0a25327 | ||
|
|
6a0a945986 | ||
|
|
3fc2dfb31a | ||
|
|
cd2d7db7b2 | ||
|
|
8dc3e5efa8 | ||
|
|
e76c5068d1 | ||
|
|
6f4ffee1e4 | ||
|
|
84d596ee47 | ||
|
|
a572637e4c | ||
|
|
3c089506ff | ||
|
|
8639e08920 | ||
|
|
936a51578a | ||
|
|
971a319764 | ||
|
|
de475ec4eb | ||
|
|
3e2c9b4b94 | ||
|
|
e43cd3a8da | ||
|
|
02a66466fe | ||
|
|
31fef1a55d | ||
|
|
316292c914 | ||
|
|
2faf3fe10d | ||
|
|
88da878c97 | ||
|
|
ff0f37ceea | ||
|
|
2784f641ba | ||
|
|
d202200a88 | ||
|
|
fd6d6350c8 | ||
|
|
e78ab6bca1 | ||
|
|
c6bdbc987a | ||
|
|
4b47de5b9e | ||
|
|
34dbc5a872 | ||
|
|
ea3afa6720 | ||
|
|
dc08efacf9 | ||
|
|
c173bf5104 | ||
|
|
2b650e6b6d | ||
|
|
a9eef6018c | ||
|
|
ac667b7ecd | ||
|
|
9f239789b9 | ||
|
|
fcad60d908 | ||
|
|
bc22851dd2 | ||
|
|
3b2d323448 | ||
|
|
c1844c9be2 | ||
|
|
cb73922a26 | ||
|
|
b413513999 | ||
|
|
8db6f49e64 | ||
|
|
6441977a7c | ||
|
|
3dbfc85aa9 | ||
|
|
0e9fdeeab0 | ||
|
|
4033c19323 | ||
|
|
34e2b657fd | ||
|
|
66fea22f60 | ||
|
|
36d7973005 | ||
|
|
057dcc218d | ||
|
|
f857d87475 | ||
|
|
d17b4340e9 | ||
|
|
bb58544a70 | ||
|
|
0b6375ae63 | ||
|
|
d6f886fbe2 | ||
|
|
a27b1b2648 | ||
|
|
c6e0379a00 | ||
|
|
25aa4255dc | ||
|
|
ca7b4e5477 | ||
|
|
717d2e09c9 | ||
|
|
d1771bbe17 | ||
|
|
7b1abacfe6 | ||
|
|
f1fe913527 | ||
|
|
7a6d1d3378 | ||
|
|
a307519e94 | ||
|
|
f1c63939f9 | ||
|
|
4997fbdbd9 | ||
|
|
1296dde15b | ||
|
|
dc760f9583 | ||
|
|
4105f90aaa | ||
|
|
5eb487ed20 | ||
|
|
1da965616b | ||
|
|
acd55cf7d6 | ||
|
|
b24272474d | ||
|
|
04f33c8034 | ||
|
|
aaaa00f1c9 | ||
|
|
bd38d1436e | ||
|
|
7409cd8a27 | ||
|
|
7b3a2b07ee | ||
|
|
056bebd4f4 | ||
|
|
c11ffe93c0 | ||
|
|
cb67c14a51 | ||
|
|
f8cec95d7a | ||
|
|
0000185875 | ||
|
|
99f84de368 | ||
|
|
70c61270dc | ||
|
|
0ec2d918bb | ||
|
|
2b25823253 | ||
|
|
6eafd73d2c | ||
|
|
3efc31c68f | ||
|
|
7d21f7bfdd | ||
|
|
77403596aa | ||
|
|
150f676332 | ||
|
|
216a2c3cdb | ||
|
|
51e129b5c6 | ||
|
|
dbf1452968 | ||
|
|
e75c285049 | ||
|
|
d872467d2c | ||
|
|
10d96be3c3 | ||
|
|
e4d9ec64cd | ||
|
|
4328f72bfb | ||
|
|
f0650a6135 | ||
|
|
60b08b9b08 | ||
|
|
41d21c78ef | ||
|
|
6be63b88f0 | ||
|
|
80117d8ab6 | ||
|
|
eecf1d5d82 | ||
|
|
4e96d11cd0 | ||
|
|
d147da1b4a | ||
|
|
df4ebb286d | ||
|
|
a398184081 | ||
|
|
7241177421 | ||
|
|
a06ba9105b | ||
|
|
a649d18cd7 | ||
|
|
024ecc1752 | ||
|
|
6e0e46435e | ||
|
|
2c06397fd9 | ||
|
|
151999c582 | ||
|
|
01cfeb65b2 | ||
|
|
bf20e5a9e8 | ||
|
|
42993de739 | ||
|
|
b26e214001 | ||
|
|
c2d26e21c3 | ||
|
|
e3170504b8 | ||
|
|
80da5917fa | ||
|
|
59f0dca7c7 | ||
|
|
4a925d192f | ||
|
|
78c30b847e | ||
|
|
b49f54144e | ||
|
|
2c1c2a4a8a | ||
|
|
83a9e916e4 | ||
|
|
da6e16b3a4 | ||
|
|
8039ab312a | ||
|
|
d533f46cd7 | ||
|
|
5b1737b817 | ||
|
|
ce010c24ec | ||
|
|
ee02a073cd | ||
|
|
35bc4e3aad | ||
|
|
22c1743886 | ||
|
|
1fbcb3c3e5 | ||
|
|
1ed737c3b9 | ||
|
|
9879a6eb99 | ||
|
|
41bb7a8564 | ||
|
|
84325edeb8 | ||
|
|
7078937311 | ||
|
|
7668e8d262 | ||
|
|
d905021252 | ||
|
|
8269e4b300 | ||
|
|
9922c42f5e | ||
|
|
460f25e848 | ||
|
|
8c9aa2242b | ||
|
|
9ae6ba4d66 | ||
|
|
636242283b | ||
|
|
7c59a5b4bd | ||
|
|
3114672989 | ||
|
|
e7cf5fc841 | ||
|
|
8a2e0eef7c | ||
|
|
7bfaf462c8 | ||
|
|
450696fa60 | ||
|
|
228c1a85e8 | ||
|
|
f97c4ae5c9 | ||
|
|
94135827ce | ||
|
|
cd8d9989cf | ||
|
|
a687f26961 | ||
|
|
b84836ed95 | ||
|
|
3b77663481 | ||
|
|
34a0abe0c8 | ||
|
|
286dcef0f0 | ||
|
|
ff3f376c07 | ||
|
|
3fb6b0e072 | ||
|
|
aa6d616d69 | ||
|
|
e63b605b2a | ||
|
|
8bdc3ec35a | ||
|
|
2ddd810dea | ||
|
|
693ad112ba | ||
|
|
73ea3c60a0 | ||
|
|
9a6fca87ff | ||
|
|
82db655a56 | ||
|
|
9a618d4dc0 | ||
|
|
a8d6fcd952 | ||
|
|
1de4976915 | ||
|
|
99cf9904f9 | ||
|
|
5ed587ddcd | ||
|
|
d040380e57 | ||
|
|
d4f99ca080 | ||
|
|
67ed035f21 | ||
|
|
6694485388 | ||
|
|
34e5ba99bc | ||
|
|
358bf0a856 | ||
|
|
21e3c2ae73 | ||
|
|
59f1bff046 | ||
|
|
7f026e8271 | ||
|
|
06a6cf7fac | ||
|
|
bbe47fbb55 | ||
|
|
423cd7807b | ||
|
|
7ca8391739 | ||
|
|
cfd6639f4d | ||
|
|
15329af94d | ||
|
|
bc058332d3 | ||
|
|
27f1231479 | ||
|
|
181bd823c4 | ||
|
|
55403d9bea | ||
|
|
7d18e2bcd8 | ||
|
|
518642d0d7 | ||
|
|
7be232e33e | ||
|
|
9080649180 | ||
|
|
2c3ed2ab73 | ||
|
|
9600378178 | ||
|
|
d8f5607509 | ||
|
|
cdb5cf37e7 | ||
|
|
06013fabec | ||
|
|
13f482f3fe | ||
|
|
aeb33432af | ||
|
|
7bb7bb396a | ||
|
|
59a6c3b3a0 | ||
|
|
13608fbdad | ||
|
|
2567a9441e | ||
|
|
58bc4f7387 | ||
|
|
9e7f03236e | ||
|
|
8898650842 | ||
|
|
789ff679a9 | ||
|
|
a68bdd6118 | ||
|
|
c56eaadfa0 | ||
|
|
0e2243e620 | ||
|
|
e3a5102624 | ||
|
|
906de27922 | ||
|
|
a2bb8515f9 | ||
|
|
a6c1b5bf59 | ||
|
|
7a667abc73 | ||
|
|
d6ab633e2c | ||
|
|
2e03c7f9f6 | ||
|
|
3746d296b0 | ||
|
|
a789be737a | ||
|
|
2d078a212a | ||
|
|
7cb23fd803 | ||
|
|
03e8aa31f4 | ||
|
|
391a9b0de5 | ||
|
|
ac50a0119a | ||
|
|
0c802677c4 | ||
|
|
63e2ef4a31 | ||
|
|
c40a266910 | ||
|
|
c0bb1e8c7c | ||
|
|
25dc3bab8f | ||
|
|
cfef9a747e | ||
|
|
a5365559d7 | ||
|
|
a4988a28b4 | ||
|
|
0c94660806 | ||
|
|
313f87ebb9 | ||
|
|
3b3807e8df | ||
|
|
f487df2961 | ||
|
|
9e457f30ae | ||
|
|
17dde3a7b9 | ||
|
|
17a2c9e311 | ||
|
|
3119fc660f | ||
|
|
6dffdd8152 | ||
|
|
2b4d27d2cf | ||
|
|
5d3e08227e | ||
|
|
348ae0b61d | ||
|
|
05cab33dad | ||
|
|
55bee713e9 | ||
|
|
7417dc5923 | ||
|
|
099e0a6e24 | ||
|
|
a6530f4db1 | ||
|
|
4b1b7591a6 | ||
|
|
be2413b9a8 | ||
|
|
5040a37a31 | ||
|
|
5267365b4f | ||
|
|
4484bf33fa | ||
|
|
9046273ebd | ||
|
|
b89a59ca55 | ||
|
|
0831ad6e40 | ||
|
|
ee218ecd44 | ||
|
|
3078156dbb | ||
|
|
7089782ba1 | ||
|
|
d03119f7e9 | ||
|
|
8150cd4317 | ||
|
|
f371ac9c74 | ||
|
|
8c77f65cdb | ||
|
|
d7f06b9e6e | ||
|
|
74e0d03b8f | ||
|
|
9d4d0cecdb | ||
|
|
f48d7a0826 | ||
|
|
5940292840 | ||
|
|
7302a54710 | ||
|
|
e3f4ae1cc7 | ||
|
|
ac4880cb0d | ||
|
|
d545900759 | ||
|
|
9d091bbf6a | ||
|
|
07850c7cb2 | ||
|
|
8151f3b540 | ||
|
|
7339e46bfb | ||
|
|
a8ac403e30 | ||
|
|
605e70f095 | ||
|
|
ae8686ef25 | ||
|
|
2dfb9f9618 | ||
|
|
c3a30bb481 | ||
|
|
3b68fc3e9a | ||
|
|
ba532536e3 | ||
|
|
9040d60977 | ||
|
|
9001728772 | ||
|
|
65d581770e | ||
|
|
ca76572eae | ||
|
|
dde8fd65e5 | ||
|
|
d04a8bff09 | ||
|
|
80fbfd77e8 | ||
|
|
767e58bf94 | ||
|
|
5967ce25fd | ||
|
|
3f42c5bdb9 | ||
|
|
ced2c18da1 | ||
|
|
f5ad03f5d9 | ||
|
|
897786bce4 | ||
|
|
0913389698 | ||
|
|
3ebda174fb | ||
|
|
dcf6469ded | ||
|
|
94ae7a678b | ||
|
|
a8306f9f37 | ||
|
|
31e4683183 | ||
|
|
a23290986a | ||
|
|
86ab893a63 | ||
|
|
cbfefc8fc3 | ||
|
|
a6f8b2c14e | ||
|
|
0fa0b7e950 | ||
|
|
01ce26cbf3 | ||
|
|
a705824b0c | ||
|
|
bd6617ea55 | ||
|
|
cf0a090704 | ||
|
|
62c8685154 | ||
|
|
c997f6ee05 | ||
|
|
9230bf5fe1 | ||
|
|
644dfb0fd3 | ||
|
|
0588dafe6b | ||
|
|
087e0389bb | ||
|
|
60c0c4dc76 | ||
|
|
45c590a3bf | ||
|
|
1c344f97f8 | ||
|
|
14f4e1aa57 | ||
|
|
eba99c84ba | ||
|
|
e9dddca86d | ||
|
|
30baff22ea | ||
|
|
0ba9889025 | ||
|
|
2b8635f0aa | ||
|
|
4fb271b3bb | ||
|
|
f892a00b99 | ||
|
|
b67aca0ffc | ||
|
|
a037575ebc | ||
|
|
1bb5f9f983 | ||
|
|
bc81154c46 | ||
|
|
9bd6b11ddf | ||
|
|
8941448866 | ||
|
|
49f5f15b98 | ||
|
|
a610618057 | ||
|
|
906dd8d6d4 | ||
|
|
9e22f4a6e6 | ||
|
|
1a911a8b99 | ||
|
|
1eb0d3bbab | ||
|
|
6242ac64ed | ||
|
|
be57170bf9 | ||
|
|
8bc857cf4d | ||
|
|
ab41a5f24a | ||
|
|
89a8817ce6 | ||
|
|
3392f11b64 | ||
|
|
5c5e450a1e | ||
|
|
a92d5f41c9 | ||
|
|
d595a64169 | ||
|
|
b3467b5d17 | ||
|
|
e56ba84094 | ||
|
|
cf45f31712 | ||
|
|
d976bf0966 | ||
|
|
f3f38cf4fd | ||
|
|
8bc52cdb55 | ||
|
|
e890d73de7 | ||
|
|
f9fbb63ecb | ||
|
|
7399caa066 | ||
|
|
c57ef8853c | ||
|
|
91bfdf0e75 | ||
|
|
f3e655b10d | ||
|
|
e4ad229a5a | ||
|
|
4e60d2b92e | ||
|
|
43fa30248c | ||
|
|
906cb36adf | ||
|
|
75f08f8cb9 | ||
|
|
6b12c55278 | ||
|
|
1b6ae9406e | ||
|
|
def20a4d31 | ||
|
|
5fe0613a97 | ||
|
|
d1b1db25ed | ||
|
|
d288160c7f | ||
|
|
cef10c1228 | ||
|
|
2314c08265 | ||
|
|
716899f919 | ||
|
|
d040de541a | ||
|
|
bc82dac61c | ||
|
|
2e50375eed | ||
|
|
8f05b638b3 | ||
|
|
ed1dc584d1 | ||
|
|
a28a861509 | ||
|
|
8b3beba93f | ||
|
|
e9e01e965e | ||
|
|
1b3c58c2c2 | ||
|
|
4217aa75e0 | ||
|
|
7bec92b7bf | ||
|
|
2c230fb80d | ||
|
|
b533d31fad | ||
|
|
21465c8f32 | ||
|
|
7ac0e9eb49 | ||
|
|
383876ddf4 | ||
|
|
1631452669 | ||
|
|
b983746888 | ||
|
|
39c5189c1f | ||
|
|
4b63a14198 | ||
|
|
0d905a7124 | ||
|
|
161759b99a | ||
|
|
8293016348 | ||
|
|
89d43ef4d7 | ||
|
|
0b39359d1c | ||
|
|
c96098540b | ||
|
|
ace9e8c3d8 | ||
|
|
bdf559bb2b | ||
|
|
6eb208adb5 | ||
|
|
77042f9d47 | ||
|
|
46dcd07f39 | ||
|
|
d4cb5b8dad | ||
|
|
90f5192055 | ||
|
|
5ebd10e43f | ||
|
|
b7f78335e1 | ||
|
|
ff375b71cb | ||
|
|
338e17ff87 | ||
|
|
a07430c088 | ||
|
|
45444316cb | ||
|
|
b209fd0c2c | ||
|
|
c9524e9b3a | ||
|
|
8bb257d4db | ||
|
|
7ba38d80f1 | ||
|
|
cadcc3e7c3 | ||
|
|
852be182f5 | ||
|
|
8619a2035c | ||
|
|
67100aa7bb | ||
|
|
225e5fc9d7 | ||
|
|
a3bc8932d4 | ||
|
|
c23811e1ab | ||
|
|
eea5b0a748 | ||
|
|
01a4327c2b | ||
|
|
41993fe5da | ||
|
|
495154b2b5 | ||
|
|
190daa76dd | ||
|
|
4bff854a04 | ||
|
|
c5bf7b523f | ||
|
|
403490364a | ||
|
|
46cb9dd346 | ||
|
|
46b94bc130 | ||
|
|
56831cec63 | ||
|
|
69d6de2fe7 | ||
|
|
f89c442730 | ||
|
|
55bfbfd5b0 | ||
|
|
ecb059b661 | ||
|
|
0dc0af015f | ||
|
|
4eb31f1fd2 | ||
|
|
8af2fc7bcc | ||
|
|
22d4083c8c | ||
|
|
abfd9c355c | ||
|
|
fe0f16812f | ||
|
|
16b892ccec | ||
|
|
7d4d08c59f | ||
|
|
a688e47934 | ||
|
|
591915a2cd | ||
|
|
88fa595d59 | ||
|
|
19a86eb5a3 | ||
|
|
b21b0adca7 | ||
|
|
c6a3cff644 | ||
|
|
7217bba7e7 | ||
|
|
661d5e41a1 | ||
|
|
4deec0cb38 | ||
|
|
971c88da5e | ||
|
|
4886dbe035 | ||
|
|
db32074439 | ||
|
|
3d89e1f203 | ||
|
|
a612f55739 | ||
|
|
5eb0bf6736 | ||
|
|
0f978b983a | ||
|
|
2c68bb0305 | ||
|
|
e97081e8cd | ||
|
|
1d228fa819 | ||
|
|
a5b4dd2604 | ||
|
|
cd92b1dccb | ||
|
|
ad48f4796c | ||
|
|
3c6dd3d721 | ||
|
|
4b74796c07 | ||
|
|
120c07ddf5 | ||
|
|
35432880b2 | ||
|
|
f35f0212dd | ||
|
|
122f182a4c | ||
|
|
a444198843 | ||
|
|
3976489984 | ||
|
|
9c1184bd29 | ||
|
|
fc6d641643 | ||
|
|
2578ac15b6 | ||
|
|
aeab29aa38 | ||
|
|
e7a065a521 | ||
|
|
934f56b553 | ||
|
|
465dd9ba96 | ||
|
|
3dcb3d3e2c | ||
|
|
7f8ee17b40 | ||
|
|
dd3f8f4bee | ||
|
|
b43c29745b | ||
|
|
6e65f3408d | ||
|
|
72e10cfad6 | ||
|
|
02ab24335a | ||
|
|
85b824babc | ||
|
|
7a02a31440 | ||
|
|
3935d978ac | ||
|
|
960058803a | ||
|
|
21bccedf9b | ||
|
|
4f25dfa6d3 | ||
|
|
5ac194911f | ||
|
|
e7a4c47f0a | ||
|
|
849a5476ab | ||
|
|
3dd2384458 | ||
|
|
38dd58315d | ||
|
|
1fa39ad20d | ||
|
|
38a3193a61 | ||
|
|
63590e2e7e | ||
|
|
511a48adde | ||
|
|
3b394c1c89 | ||
|
|
e6e2ba9cfb | ||
|
|
ef1b7644f3 | ||
|
|
3e6a271ad8 | ||
|
|
004094d66f | ||
|
|
85bae12a00 | ||
|
|
6ccf8a4d2d | ||
|
|
9e5cf1e1a4 | ||
|
|
bad7399eeb | ||
|
|
88ebd14799 | ||
|
|
1353929d44 | ||
|
|
d0074d0d8a | ||
|
|
41c83a7e19 | ||
|
|
0cb9f1c0d7 | ||
|
|
ac3d037dc4 | ||
|
|
b580b7bd2c | ||
|
|
fdc9534fc7 | ||
|
|
345d346224 | ||
|
|
d0af03b723 | ||
|
|
d0fb37e264 | ||
|
|
28b7302c9e | ||
|
|
eee9561656 | ||
|
|
6474ca9540 | ||
|
|
0c24510682 | ||
|
|
8d86585928 | ||
|
|
8818a9bb6f | ||
|
|
c28b5a22fb | ||
|
|
8bd784e5ab | ||
|
|
3f21a05e3e | ||
|
|
a6ff90ad20 | ||
|
|
86c2686b9a | ||
|
|
390e19ecdd | ||
|
|
47671ac332 | ||
|
|
995d285fdd | ||
|
|
0c8aca3ef8 | ||
|
|
7ef89acf81 | ||
|
|
0f9dc4954a | ||
|
|
7477a22421 | ||
|
|
7f87825186 | ||
|
|
1d52e06532 | ||
|
|
2eb1901073 | ||
|
|
29ec257e14 | ||
|
|
bd4efe8c2d | ||
|
|
baac8199da | ||
|
|
3d4cf4d8d5 | ||
|
|
fc92779ddc | ||
|
|
be92f3866c | ||
|
|
68f2528f23 | ||
|
|
db417abc18 | ||
|
|
a7e30adc28 | ||
|
|
4ba58d8132 | ||
|
|
6410355d71 | ||
|
|
6eb0dfb43f | ||
|
|
79b613b0e5 | ||
|
|
254c411bd9 | ||
|
|
72785a69cb | ||
|
|
36781481bb | ||
|
|
133828edeb | ||
|
|
dff4119765 | ||
|
|
bb04224187 | ||
|
|
482f0bd91d | ||
|
|
910ae49fca | ||
|
|
2c91bfca96 | ||
|
|
60bed99c3b | ||
|
|
eeba0e7a63 | ||
|
|
795f715833 | ||
|
|
4bc061117a | ||
|
|
f87ddffc64 | ||
|
|
738e8c65c8 | ||
|
|
d76121b147 | ||
|
|
8f91689b3f | ||
|
|
ee59f36b77 | ||
|
|
ae57c7a232 | ||
|
|
d6cae5862d | ||
|
|
300e055933 | ||
|
|
f2a27ea970 | ||
|
|
597a7a8a03 | ||
|
|
2f4be3c9c4 | ||
|
|
fb12f5de52 | ||
|
|
b42bffa6fa | ||
|
|
f79c08b235 | ||
|
|
7abd1aceca | ||
|
|
9b6faa5644 | ||
|
|
021bbc12ba | ||
|
|
f8be5a284c | ||
|
|
68eedd578a | ||
|
|
6ba587155a | ||
|
|
b9afd6012c | ||
|
|
0b265012bc | ||
|
|
ee20b00f58 | ||
|
|
079151eeea | ||
|
|
30f98aec3c | ||
|
|
f1e8b5c01d | ||
|
|
c90f3cb1ef | ||
|
|
f277fb3bb8 | ||
|
|
f4465c9d32 | ||
|
|
fefc4ba60e | ||
|
|
92aecb3bec | ||
|
|
47ed820dea | ||
|
|
52f1ce81fb | ||
|
|
555932d67e | ||
|
|
22f7d1d48b | ||
|
|
e8d46982d8 | ||
|
|
6abedf5f87 | ||
|
|
aa624b4df0 | ||
|
|
8885b8a354 | ||
|
|
9bd2de06ee | ||
|
|
62486a17b6 | ||
|
|
1187c13170 | ||
|
|
ff44003ea3 | ||
|
|
686713dc4b | ||
|
|
0f8b8bbd5b | ||
|
|
abdb5f7587 | ||
|
|
89a41826c1 | ||
|
|
e46b3e6cf3 | ||
|
|
7668276a99 | ||
|
|
770e90064d | ||
|
|
283a5501be | ||
|
|
7c4d35cf28 | ||
|
|
564dd993b7 | ||
|
|
a1419b9dc0 | ||
|
|
f4d176011d | ||
|
|
3df36721d6 | ||
|
|
75ac7e91c8 | ||
|
|
ff1cad6e63 | ||
|
|
0d80ded2d3 | ||
|
|
a02eb39bf1 | ||
|
|
7b721836c8 | ||
|
|
b34acfd4eb | ||
|
|
e4ef2641f8 | ||
|
|
079e2f4cb2 | ||
|
|
bed82d68ab | ||
|
|
7f86a9e1ba | ||
|
|
80867bbc54 | ||
|
|
55191c6838 | ||
|
|
7453130c63 | ||
|
|
a4c01e4df1 | ||
|
|
c643346589 | ||
|
|
894a008daa | ||
|
|
16d7ccdf0b | ||
|
|
936f7fdb3d | ||
|
|
0966889ab9 | ||
|
|
62585aa445 | ||
|
|
efb711963f | ||
|
|
4e44b197c2 | ||
|
|
6ea9b36cc9 | ||
|
|
0328c1677c | ||
|
|
64c31af529 | ||
|
|
e2804dbbcb | ||
|
|
2184af09d9 | ||
|
|
f18439fa14 | ||
|
|
fd74b79b61 | ||
|
|
c1e036d4f7 | ||
|
|
6f1aee990c | ||
|
|
bd05e97c29 | ||
|
|
ddf95e2750 | ||
|
|
4fec1bf717 | ||
|
|
be9101b51f | ||
|
|
11153cf2ca | ||
|
|
787d550a1f | ||
|
|
3d7d8b51d2 | ||
|
|
5a1bd13831 | ||
|
|
34b5566333 | ||
|
|
a6dcaa2327 | ||
|
|
3e7e99831a | ||
|
|
b642cd6840 | ||
|
|
0e2fa40539 | ||
|
|
7175200779 | ||
|
|
30d60021f4 | ||
|
|
82b226712f | ||
|
|
331e6645c6 | ||
|
|
426651d827 | ||
|
|
22a5832c01 | ||
|
|
44093c9342 | ||
|
|
2b7eeffd5b | ||
|
|
924bcca0e2 | ||
|
|
d01fbeac04 | ||
|
|
55492535c6 | ||
|
|
baf0533466 | ||
|
|
cbda6b8c58 | ||
|
|
319452537e | ||
|
|
f6dcb6b993 | ||
|
|
a4764e87e0 | ||
|
|
659dfd36ed | ||
|
|
f043c9cc7e | ||
|
|
049670654e | ||
|
|
dcf630fd9a | ||
|
|
4c47d8334c | ||
|
|
d44e76a6aa | ||
|
|
e3f7bd319b | ||
|
|
51083e9659 | ||
|
|
0c67e271df | ||
|
|
232de40457 | ||
|
|
3fe2924a60 | ||
|
|
5c21e220ff | ||
|
|
58f757b91d | ||
|
|
c43cd7bf7a |
14
.gitignore
vendored
14
.gitignore
vendored
@@ -9,17 +9,18 @@ config/fb_config.yml
|
||||
config/oauth_keys.yml
|
||||
config/initializers/secret_token.rb
|
||||
config/redis.conf
|
||||
config/deploy_config.yml
|
||||
.bundle
|
||||
vendor/bundle/*
|
||||
config/database.yml
|
||||
|
||||
# Generated files
|
||||
log/*
|
||||
public/stylesheets/application.css
|
||||
public/stylesheets/sessions.css
|
||||
public/stylesheets/ui.css
|
||||
public/stylesheets/mobile.css
|
||||
public/stylesheets/*.css
|
||||
public/diaspora
|
||||
spec/fixtures/users.yaml
|
||||
spec/fixtures/*.y*ml
|
||||
spec/fixtures/*.fixture.*
|
||||
coverage/*
|
||||
|
||||
# Uploded files and local files
|
||||
public/uploads/*
|
||||
@@ -44,3 +45,6 @@ nbproject
|
||||
patches-*
|
||||
capybara-*.html
|
||||
dump.rdb
|
||||
|
||||
#Rubinius's JIT
|
||||
*.rbc
|
||||
|
||||
6
.rspec
6
.rspec
@@ -1,3 +1,3 @@
|
||||
--color
|
||||
--require rspec/instafail
|
||||
--format RSpec::Instafail
|
||||
--format Fuubar
|
||||
--profile
|
||||
--color
|
||||
46
Gemfile
46
Gemfile
@@ -1,6 +1,8 @@
|
||||
source 'http://rubygems.org'
|
||||
|
||||
gem 'mysql2', '0.2.6'
|
||||
gem 'rails', '3.0.3'
|
||||
gem 'foreigner', '0.9.1'
|
||||
|
||||
gem 'bundler', '>= 1.0.0'
|
||||
gem 'chef', '0.9.12', :require => false
|
||||
@@ -9,63 +11,77 @@ gem 'nokogiri', '1.4.3.1'
|
||||
|
||||
#Security
|
||||
gem 'devise', '1.1.3'
|
||||
gem 'devise-mongo_mapper', :git => 'git://github.com/collectiveidea/devise-mongo_mapper', :ref => 'fa2f20310e0988295adc'
|
||||
gem 'devise_invitable','0.3.5'
|
||||
gem 'devise_invitable', :git => 'git://github.com/zhitomirskiyi/devise_invitable.git', :branch => '0.3.5'
|
||||
|
||||
#Authentication
|
||||
gem 'omniauth', '0.1.6'
|
||||
gem 'twitter', :git => 'git://github.com/jnunemaker/twitter.git', :ref => 'ef122bbb280e229ed343'
|
||||
|
||||
#Mongo
|
||||
gem 'mongo_mapper', :branch => 'rails3', :git => 'git://github.com/jnunemaker/mongomapper.git', :ref => '108510cc9b96bfbcf7f0'
|
||||
gem 'bson_ext', '1.1'
|
||||
gem 'bson', '1.1'
|
||||
|
||||
#Views
|
||||
gem 'haml', '3.0.25'
|
||||
gem 'will_paginate', '3.0.pre2'
|
||||
|
||||
#Inflected translations
|
||||
gem 'i18n-inflector-rails', '~> 1.0'
|
||||
|
||||
#Tags
|
||||
gem 'acts-as-taggable-on', :git => 'git://github.com/diaspora/acts-as-taggable-on.git'
|
||||
|
||||
#Uncatagorized
|
||||
gem 'roxml', :git => 'git://github.com/Empact/roxml.git', :ref => '7ea9a9ffd2338aaef5b0'
|
||||
gem 'addressable', '2.2.2', :require => 'addressable/uri'
|
||||
gem 'json', '1.4.6'
|
||||
gem 'http_accept_language', :git => 'git://github.com/iain/http_accept_language.git', :ref => '0b78aa7849fc90cf9e12'
|
||||
|
||||
gem 'thin', '1.2.7', :require => false
|
||||
gem 'thin', '1.2.8', :require => false
|
||||
|
||||
#Websocket
|
||||
gem 'em-websocket', :git => 'git://github.com/igrigorik/em-websocket', :ref => 'e278f5a1c4db60be7485'
|
||||
|
||||
#File uploading
|
||||
gem 'carrierwave', :git => 'git://github.com/rsofaer/carrierwave.git' , :branch => 'master' #Untested mongomapper branch
|
||||
gem 'carrierwave', '0.5.2'
|
||||
gem "fog", '0.3.25'
|
||||
gem "excon", "0.2.4"
|
||||
gem 'mini_magick', '3.2'
|
||||
gem 'aws', '2.3.32' # upgrade to 2.4 breaks 1.8 >.<
|
||||
|
||||
gem 'fastercsv', '1.5.4', :require => false
|
||||
gem 'jammit', '0.5.4'
|
||||
gem 'rest-client', '1.6.1'
|
||||
gem 'typhoeus'
|
||||
|
||||
#Backups
|
||||
gem 'cloudfiles', '1.4.10', :require => false
|
||||
|
||||
#Queue
|
||||
gem 'resque', '1.10.0'
|
||||
gem 'SystemTimer', '1.2.1' unless RUBY_VERSION.include? '1.9'
|
||||
gem 'SystemTimer', '1.2.1' unless RUBY_VERSION.include? '1.9' || RUBY_PLATFORM =~ 'win32'
|
||||
|
||||
group :development do
|
||||
gem 'capistrano', '2.5.19', :require => false
|
||||
gem 'capistrano-ext', '1.2.1', :require => false
|
||||
end
|
||||
|
||||
group :test, :development do
|
||||
gem 'factory_girl_rails'
|
||||
gem 'factory_girl_rails', :require => false
|
||||
gem 'ruby-debug-base19', '0.11.23' if RUBY_VERSION.include? '1.9.1'
|
||||
gem 'ruby-debug19' if RUBY_VERSION.include? '1.9'
|
||||
gem 'ruby-debug' if RUBY_VERSION.include? '1.8'
|
||||
gem 'ruby-debug' if defined?(Rubinius).nil? && RUBY_VERSION.include?('1.8')
|
||||
gem 'launchy'
|
||||
end
|
||||
|
||||
group :test do
|
||||
gem 'factory_girl_rails'
|
||||
gem 'fixture_builder', '~> 0.2.0'
|
||||
gem 'capybara', '~> 0.3.9'
|
||||
gem 'cucumber-rails', '0.3.2'
|
||||
gem 'rspec', '>= 2.0.0'
|
||||
gem 'rspec-rails', '>= 2.0.0'
|
||||
gem 'mocha'
|
||||
gem 'database_cleaner', '0.5.2'
|
||||
gem 'rcov'
|
||||
gem 'database_cleaner', '0.6.0'
|
||||
gem 'webmock', :require => false
|
||||
gem 'jasmine', :path => 'vendor/gems/jasmine', :require => false
|
||||
gem 'mongrel', :require => false if RUBY_VERSION.include? '1.8'
|
||||
gem 'rspec-instafail', :require => false
|
||||
gem 'rspec-instafail', '>= 0.1.7', :require => false
|
||||
gem 'fuubar'
|
||||
end
|
||||
|
||||
184
Gemfile.lock
184
Gemfile.lock
@@ -8,12 +8,11 @@ GIT
|
||||
nokogiri (>= 1.3.3)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/collectiveidea/devise-mongo_mapper
|
||||
revision: fa2f20310e0988295adc192255d3b1cedee1b412
|
||||
ref: fa2f20310e0988295adc
|
||||
remote: git://github.com/diaspora/acts-as-taggable-on.git
|
||||
revision: c3592fe1a906f6ff1cd12766c5cf1152c51eec40
|
||||
specs:
|
||||
devise-mongo_mapper (0.0.1)
|
||||
devise (~> 1.1.0)
|
||||
acts-as-taggable-on (2.0.6)
|
||||
rails (>= 3.0)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/iain/http_accept_language.git
|
||||
@@ -31,17 +30,6 @@ GIT
|
||||
addressable (>= 2.1.1)
|
||||
eventmachine (>= 0.12.9)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/jnunemaker/mongomapper.git
|
||||
revision: 108510cc9b96bfbcf7f095ec037bce30cb6aa2c9
|
||||
ref: 108510cc9b96bfbcf7f0
|
||||
branch: rails3
|
||||
specs:
|
||||
mongo_mapper (0.8.6)
|
||||
activemodel (~> 3.0.0)
|
||||
activesupport (~> 3.0.0)
|
||||
plucky (~> 0.3.6)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/jnunemaker/twitter.git
|
||||
revision: ef122bbb280e229ed34347c235c68aa9349d0d8e
|
||||
@@ -56,12 +44,12 @@ GIT
|
||||
simple_oauth (~> 0.1.2)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/rsofaer/carrierwave.git
|
||||
revision: a42dfa25023775be82d7eb9bc9edb675986b1f40
|
||||
branch: master
|
||||
remote: git://github.com/zhitomirskiyi/devise_invitable.git
|
||||
revision: 85abb5fef4ab4f74db818ed3d8104c2f7d24b94e
|
||||
branch: 0.3.5
|
||||
specs:
|
||||
carrierwave (0.5.0)
|
||||
activesupport (~> 3.0)
|
||||
devise_invitable (0.3.5)
|
||||
devise (~> 1.1.0)
|
||||
|
||||
PATH
|
||||
remote: vendor/gems/jasmine
|
||||
@@ -106,17 +94,23 @@ GEM
|
||||
activesupport (= 3.0.3)
|
||||
activesupport (3.0.3)
|
||||
addressable (2.2.2)
|
||||
arel (2.0.7)
|
||||
arel (2.0.9)
|
||||
aws (2.3.32)
|
||||
activesupport
|
||||
http_connection
|
||||
uuidtools
|
||||
xml-simple
|
||||
bcrypt-ruby (2.1.4)
|
||||
bson (1.1)
|
||||
bson_ext (1.1)
|
||||
builder (2.1.2)
|
||||
bunny (0.6.0)
|
||||
capistrano (2.5.19)
|
||||
highline
|
||||
net-scp (>= 1.0.0)
|
||||
net-sftp (>= 2.0.0)
|
||||
net-ssh (>= 2.0.14)
|
||||
net-ssh-gateway (>= 1.0.0)
|
||||
capistrano-ext (1.2.1)
|
||||
capistrano (>= 1.0.0)
|
||||
capybara (0.3.9)
|
||||
culerity (>= 0.2.4)
|
||||
mime-types (>= 1.16)
|
||||
@@ -124,24 +118,26 @@ GEM
|
||||
rack (>= 1.0.0)
|
||||
rack-test (>= 0.5.4)
|
||||
selenium-webdriver (>= 0.0.3)
|
||||
carrierwave (0.5.2)
|
||||
activesupport (~> 3.0)
|
||||
cgi_multipart_eof_fix (2.5.0)
|
||||
chef (0.9.12)
|
||||
bunny (>= 0.6.0)
|
||||
erubis
|
||||
extlib
|
||||
highline
|
||||
json (>= 1.4.4, <= 1.4.6)
|
||||
json (<= 1.4.6, >= 1.4.4)
|
||||
mixlib-authentication (>= 1.1.0)
|
||||
mixlib-cli (>= 1.1.0)
|
||||
mixlib-config (>= 1.1.2)
|
||||
mixlib-log (>= 1.2.0)
|
||||
moneta
|
||||
ohai (>= 0.5.7)
|
||||
rest-client (>= 1.0.4, < 1.7.0)
|
||||
rest-client (< 1.7.0, >= 1.0.4)
|
||||
uuidtools
|
||||
childprocess (0.1.6)
|
||||
childprocess (0.1.7)
|
||||
ffi (~> 0.6.3)
|
||||
closure-compiler (0.3.3)
|
||||
closure-compiler (1.0.0)
|
||||
cloudfiles (1.4.10)
|
||||
mime-types (>= 1.16)
|
||||
columnize (0.3.2)
|
||||
@@ -155,18 +151,17 @@ GEM
|
||||
term-ansicolor (~> 1.0.5)
|
||||
cucumber-rails (0.3.2)
|
||||
cucumber (>= 0.8.0)
|
||||
culerity (0.2.14)
|
||||
culerity (0.2.15)
|
||||
daemons (1.1.0)
|
||||
database_cleaner (0.5.2)
|
||||
database_cleaner (0.6.0)
|
||||
devise (1.1.3)
|
||||
bcrypt-ruby (~> 2.1.2)
|
||||
warden (~> 0.10.7)
|
||||
devise_invitable (0.3.5)
|
||||
devise (~> 1.1.0)
|
||||
diff-lcs (1.1.2)
|
||||
erubis (2.6.6)
|
||||
abstract (>= 1.0.0)
|
||||
eventmachine (0.12.10)
|
||||
excon (0.2.4)
|
||||
extlib (0.9.15)
|
||||
factory_girl (1.3.3)
|
||||
factory_girl_rails (1.0.1)
|
||||
@@ -175,13 +170,29 @@ GEM
|
||||
faraday (0.5.4)
|
||||
addressable (~> 2.2.2)
|
||||
multipart-post (~> 1.1.0)
|
||||
rack (>= 1.1.0, < 2)
|
||||
faraday_middleware (0.3.1)
|
||||
faraday (~> 0.5.3)
|
||||
rack (< 2, >= 1.1.0)
|
||||
faraday_middleware (0.3.2)
|
||||
faraday (~> 0.5.4)
|
||||
fastercsv (1.5.4)
|
||||
fastthread (1.0.7)
|
||||
ffi (0.6.3)
|
||||
rake (>= 0.8.7)
|
||||
fixture_builder (0.2.0)
|
||||
fog (0.3.25)
|
||||
builder
|
||||
excon (>= 0.2.4)
|
||||
formatador (>= 0.0.16)
|
||||
json
|
||||
mime-types
|
||||
net-ssh (~> 2.0.23)
|
||||
nokogiri (~> 1.4.3.1)
|
||||
ruby-hmac
|
||||
foreigner (0.9.1)
|
||||
formatador (0.0.16)
|
||||
fuubar (0.0.3)
|
||||
rspec (~> 2.0)
|
||||
rspec-instafail (~> 0.1.4)
|
||||
ruby-progressbar (~> 0.0.9)
|
||||
gem_plugin (0.2.3)
|
||||
gherkin (2.3.3)
|
||||
json (~> 1.4.6)
|
||||
@@ -190,16 +201,22 @@ GEM
|
||||
highline (1.6.1)
|
||||
http_connection (1.4.0)
|
||||
i18n (0.5.0)
|
||||
i18n-inflector (2.5.1)
|
||||
i18n (>= 0.4.1)
|
||||
i18n-inflector-rails (1.0.3)
|
||||
actionpack (~> 3.0)
|
||||
i18n-inflector (~> 2.5)
|
||||
railties (~> 3.0)
|
||||
jammit (0.5.4)
|
||||
closure-compiler (>= 0.1.0)
|
||||
yui-compressor (>= 0.9.1)
|
||||
json (1.4.6)
|
||||
json_pure (1.4.6)
|
||||
launchy (0.3.7)
|
||||
json_pure (1.5.1)
|
||||
launchy (0.4.0)
|
||||
configuration (>= 0.0.5)
|
||||
rake (>= 0.8.1)
|
||||
linecache (0.43)
|
||||
mail (2.2.14)
|
||||
mail (2.2.15)
|
||||
activesupport (>= 2.3.6)
|
||||
i18n (>= 0.4.0)
|
||||
mime-types (~> 1.16)
|
||||
@@ -212,20 +229,24 @@ GEM
|
||||
mixlib-cli (1.2.0)
|
||||
mixlib-config (1.1.2)
|
||||
mixlib-log (1.2.0)
|
||||
mocha (0.9.10)
|
||||
rake
|
||||
moneta (0.6.0)
|
||||
mongo (1.1)
|
||||
bson (>= 1.0.5)
|
||||
mongrel (1.1.5)
|
||||
cgi_multipart_eof_fix (>= 2.4)
|
||||
daemons (>= 1.0.3)
|
||||
fastthread (>= 1.0.1)
|
||||
gem_plugin (>= 0.2.3)
|
||||
multi_json (0.0.5)
|
||||
multi_xml (0.2.0)
|
||||
multi_xml (0.2.1)
|
||||
multipart-post (1.1.0)
|
||||
mysql2 (0.2.6)
|
||||
net-ldap (0.1.1)
|
||||
net-scp (1.0.4)
|
||||
net-ssh (>= 1.99.1)
|
||||
net-sftp (2.0.5)
|
||||
net-ssh (>= 2.0.9)
|
||||
net-ssh (2.0.24)
|
||||
net-ssh-gateway (1.0.1)
|
||||
net-ssh (>= 1.99.1)
|
||||
nokogiri (1.4.3.1)
|
||||
oa-basic (0.1.6)
|
||||
multi_json (~> 0.0.2)
|
||||
@@ -256,7 +277,7 @@ GEM
|
||||
multi_json (~> 0.0.4)
|
||||
ohai (0.5.8)
|
||||
extlib
|
||||
json (>= 1.4.4, <= 1.4.6)
|
||||
json (<= 1.4.6, >= 1.4.4)
|
||||
mixlib-cli
|
||||
mixlib-config
|
||||
mixlib-log
|
||||
@@ -267,8 +288,6 @@ GEM
|
||||
oa-enterprise (= 0.1.6)
|
||||
oa-oauth (= 0.1.6)
|
||||
oa-openid (= 0.1.6)
|
||||
plucky (0.3.6)
|
||||
mongo (~> 1.1)
|
||||
polyglot (0.3.1)
|
||||
pyu-ruby-sasl (0.0.3.2)
|
||||
rack (1.2.1)
|
||||
@@ -293,6 +312,7 @@ GEM
|
||||
rake (>= 0.8.7)
|
||||
thor (~> 0.14.4)
|
||||
rake (0.8.7)
|
||||
rcov (0.9.9)
|
||||
redis (2.1.1)
|
||||
redis-namespace (0.8.0)
|
||||
redis (< 3.0.0)
|
||||
@@ -303,55 +323,60 @@ GEM
|
||||
vegas (~> 0.1.2)
|
||||
rest-client (1.6.1)
|
||||
mime-types (>= 1.16)
|
||||
rspec (2.4.0)
|
||||
rspec-core (~> 2.4.0)
|
||||
rspec-expectations (~> 2.4.0)
|
||||
rspec-mocks (~> 2.4.0)
|
||||
rspec-core (2.4.0)
|
||||
rspec-expectations (2.4.0)
|
||||
rspec (2.5.0)
|
||||
rspec-core (~> 2.5.0)
|
||||
rspec-expectations (~> 2.5.0)
|
||||
rspec-mocks (~> 2.5.0)
|
||||
rspec-core (2.5.1)
|
||||
rspec-expectations (2.5.0)
|
||||
diff-lcs (~> 1.1.2)
|
||||
rspec-instafail (0.1.5)
|
||||
rspec-mocks (2.4.0)
|
||||
rspec-rails (2.4.1)
|
||||
rspec-instafail (0.1.7)
|
||||
rspec-mocks (2.5.0)
|
||||
rspec-rails (2.5.0)
|
||||
actionpack (~> 3.0)
|
||||
activesupport (~> 3.0)
|
||||
railties (~> 3.0)
|
||||
rspec (~> 2.4.0)
|
||||
rspec (~> 2.5.0)
|
||||
ruby-debug (0.10.4)
|
||||
columnize (>= 0.1)
|
||||
ruby-debug-base (~> 0.10.4.0)
|
||||
ruby-debug-base (0.10.4)
|
||||
linecache (>= 0.3)
|
||||
ruby-hmac (0.4.0)
|
||||
ruby-openid (2.1.8)
|
||||
ruby-openid-apps-discovery (1.2.0)
|
||||
ruby-openid (>= 2.1.7)
|
||||
ruby-progressbar (0.0.9)
|
||||
rubyntlm (0.1.1)
|
||||
rubyzip (0.9.4)
|
||||
selenium-client (1.2.18)
|
||||
selenium-rc (2.2.4)
|
||||
selenium-rc (2.3.2)
|
||||
selenium-client (>= 1.2.18)
|
||||
selenium-webdriver (0.1.2)
|
||||
selenium-webdriver (0.1.3)
|
||||
childprocess (~> 0.1.5)
|
||||
ffi (~> 0.6.3)
|
||||
json_pure
|
||||
rubyzip
|
||||
simple_oauth (0.1.3)
|
||||
sinatra (1.1.2)
|
||||
simple_oauth (0.1.4)
|
||||
sinatra (1.2.0)
|
||||
rack (~> 1.1)
|
||||
tilt (~> 1.2)
|
||||
tilt (< 2.0, >= 1.2.2)
|
||||
subexec (0.0.4)
|
||||
systemu (1.2.0)
|
||||
term-ansicolor (1.0.5)
|
||||
thin (1.2.7)
|
||||
thin (1.2.8)
|
||||
daemons (>= 1.0.9)
|
||||
eventmachine (>= 0.12.6)
|
||||
rack (>= 1.0.0)
|
||||
thor (0.14.6)
|
||||
tilt (1.2.1)
|
||||
tilt (1.2.2)
|
||||
treetop (1.4.9)
|
||||
polyglot (>= 0.3.1)
|
||||
typhoeus (0.2.4)
|
||||
mime-types
|
||||
mime-types
|
||||
tzinfo (0.3.24)
|
||||
uuidtools (2.1.1)
|
||||
uuidtools (2.1.2)
|
||||
vegas (0.1.8)
|
||||
rack (>= 1.0.0)
|
||||
warden (0.10.7)
|
||||
@@ -360,52 +385,59 @@ GEM
|
||||
addressable (>= 2.2.2)
|
||||
crack (>= 0.1.7)
|
||||
will_paginate (3.0.pre2)
|
||||
xml-simple (1.0.12)
|
||||
yui-compressor (0.9.1)
|
||||
xml-simple (1.0.14)
|
||||
yui-compressor (0.9.4)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
SystemTimer (= 1.2.1)
|
||||
acts-as-taggable-on!
|
||||
addressable (= 2.2.2)
|
||||
aws (= 2.3.32)
|
||||
bson (= 1.1)
|
||||
bson_ext (= 1.1)
|
||||
bundler (>= 1.0.0)
|
||||
capistrano (= 2.5.19)
|
||||
capistrano-ext (= 1.2.1)
|
||||
capybara (~> 0.3.9)
|
||||
carrierwave!
|
||||
carrierwave (= 0.5.2)
|
||||
chef (= 0.9.12)
|
||||
cloudfiles (= 1.4.10)
|
||||
cucumber-rails (= 0.3.2)
|
||||
database_cleaner (= 0.5.2)
|
||||
database_cleaner (= 0.6.0)
|
||||
devise (= 1.1.3)
|
||||
devise-mongo_mapper!
|
||||
devise_invitable (= 0.3.5)
|
||||
devise_invitable!
|
||||
em-websocket!
|
||||
excon (= 0.2.4)
|
||||
factory_girl_rails
|
||||
fastercsv (= 1.5.4)
|
||||
fixture_builder (~> 0.2.0)
|
||||
fog (= 0.3.25)
|
||||
foreigner (= 0.9.1)
|
||||
fuubar
|
||||
haml (= 3.0.25)
|
||||
http_accept_language!
|
||||
i18n-inflector-rails (~> 1.0)
|
||||
jammit (= 0.5.4)
|
||||
jasmine!
|
||||
json (= 1.4.6)
|
||||
launchy
|
||||
mini_magick (= 3.2)
|
||||
mocha
|
||||
mongo_mapper!
|
||||
mongrel
|
||||
mysql2 (= 0.2.6)
|
||||
nokogiri (= 1.4.3.1)
|
||||
omniauth (= 0.1.6)
|
||||
rails (= 3.0.3)
|
||||
rcov
|
||||
resque (= 1.10.0)
|
||||
rest-client (= 1.6.1)
|
||||
roxml!
|
||||
rspec (>= 2.0.0)
|
||||
rspec-instafail
|
||||
rspec-instafail (>= 0.1.7)
|
||||
rspec-rails (>= 2.0.0)
|
||||
ruby-debug
|
||||
thin (= 1.2.7)
|
||||
thin (= 1.2.8)
|
||||
twitter!
|
||||
typhoeus
|
||||
webmock
|
||||
will_paginate (= 3.0.pre2)
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
The privacy aware, personally controlled, do-it-all, open source social
|
||||
network.
|
||||
|
||||
**THIS IS PRE-ALPHA SOFTWARE AND SHOULD BE TREATED ACCORDINGLY.**
|
||||
**PLEASE, DO NOT RUN IN PRODUCTION. IT IS FUN TO GET RUNNING, BUT EXPECT THINGS
|
||||
TO BE BROKEN.**
|
||||
**THIS IS ALPHA SOFTWARE AND SHOULD BE TREATED ACCORDINGLY.**
|
||||
**IT IS FUN TO GET RUNNING, BUT EXPECT THINGS TO BE BROKEN.**
|
||||
|
||||
## Installation instructions
|
||||
|
||||
@@ -53,7 +52,7 @@ We're currently working on revising it more details on what we're going for can
|
||||
|
||||
Here is our [bug tracker](http://bugs.joindiaspora.com) and our
|
||||
[roadmap](https://github.com/diaspora/diaspora/wiki/Roadmap). Also, you can
|
||||
find see what the core team is upto [here](http://www.pivotaltracker.com/projects/61641).
|
||||
find see what the core team is up to [here](http://www.pivotaltracker.com/projects/61641).
|
||||
|
||||
|
||||
Ongoing discussion:
|
||||
@@ -61,6 +60,8 @@ Ongoing discussion:
|
||||
- [Diaspora Developer Google Group](http://groups.google.com/group/diaspora-dev)
|
||||
- [Diaspora Discussion Google Group](http://groups.google.com/group/diaspora-discuss)
|
||||
- [Diaspora Q&A site](http://diaspora.shapado.com/)
|
||||
- [#diaspora IRC channel](irc://irc.freenode.net/#diaspora)
|
||||
([join via the web client](http://webchat.freenode.net?channels=diaspora))
|
||||
- [#diaspora-dev IRC channel](irc://irc.freenode.net/#diaspora-dev)
|
||||
([join via the web client](http://webchat.freenode.net?channels=diaspora-dev))
|
||||
|
||||
|
||||
11
Termfile
11
Termfile
@@ -5,15 +5,14 @@
|
||||
# If you do
|
||||
# terminitor start
|
||||
# from the Diaspora root directory, it will open a new terminal window with
|
||||
# 4 tabs: mongo, redis, resque, and jasmine.
|
||||
# 3 tabs: redis, resque, and jasmine.
|
||||
#
|
||||
# You need to install the terminitor gem. It's not in the Gemfile because it
|
||||
# causes problems on some flavors of linux.
|
||||
# gem install terminitor
|
||||
#
|
||||
# You should set MONGO_ROOT and REDIS_ROOT before running terminitor start.
|
||||
# You should set REDIS_ROOT before running terminitor start.
|
||||
# You might want to do that in your .bash_profile.
|
||||
# export MONGO_ROOT=/full/path/to/mongo/without/the/bin
|
||||
# export REDIS_ROOT=/full/path/to/redis/without/the/bin
|
||||
# You can also set DIASPORA_ROOT in a similar way if you don't want it to be
|
||||
# the directory this file is in.
|
||||
@@ -28,13 +27,9 @@ def get_var_for(env_var_name)
|
||||
end
|
||||
end
|
||||
|
||||
before { system "sudo ls" } # this ensures mongo and redis can start right away
|
||||
before { system "sudo ls" } # this ensures redis can start right away
|
||||
|
||||
window do
|
||||
tab :name => "mongod" do
|
||||
run "cd #{get_var_for('MONGO_ROOT')}"
|
||||
run "sudo ./bin/mongod"
|
||||
end
|
||||
tab :name => "redis" do
|
||||
run "cd #{get_var_for('REDIS_ROOT')}"
|
||||
run "sudo ./bin/redis-server"
|
||||
|
||||
27
app/controllers/admins_controller.rb
Normal file
27
app/controllers/admins_controller.rb
Normal file
@@ -0,0 +1,27 @@
|
||||
class AdminsController < ApplicationController
|
||||
before_filter :authenticate_user!
|
||||
before_filter :redirect_unless_admin
|
||||
|
||||
def user_search
|
||||
user = params[:user] || {}
|
||||
user = user.delete_if {|key, value| value.blank? }
|
||||
params[:user] = user
|
||||
|
||||
if user.keys.count == 0
|
||||
@users = []
|
||||
else
|
||||
@users = User.where(params[:user]).all || []
|
||||
end
|
||||
|
||||
render 'user_search'
|
||||
end
|
||||
|
||||
def admin_inviter
|
||||
opts = {:service => 'email', :identifier => params[:identifier]}
|
||||
existing_user = Invitation.find_existing_user('email', params[:identifier])
|
||||
opts.merge!(:existing_user => existing_user) if existing_user
|
||||
Invitation.create_invitee(opts)
|
||||
flash[:notice] = "invitation sent to #{params[:identifier]}"
|
||||
redirect_to '/admins/user_search'
|
||||
end
|
||||
end
|
||||
@@ -3,37 +3,39 @@
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class ApplicationController < ActionController::Base
|
||||
#has_mobile_fu
|
||||
has_mobile_fu
|
||||
protect_from_forgery :except => :receive
|
||||
|
||||
#before_filter :mobile_except_ipad
|
||||
before_filter :set_contacts_notifications_and_status, :except => [:create, :update]
|
||||
before_filter :ensure_http_referer_is_set
|
||||
before_filter :set_header_data, :except => [:create, :update]
|
||||
before_filter :count_requests
|
||||
before_filter :set_invites
|
||||
before_filter :set_locale
|
||||
before_filter :set_git_header if (AppConfig[:git_update] && AppConfig[:git_revision])
|
||||
before_filter :which_action_and_user
|
||||
prepend_before_filter :clear_gc_stats
|
||||
before_filter :set_grammatical_gender
|
||||
|
||||
def set_contacts_notifications_and_status
|
||||
if user_signed_in?
|
||||
@aspect = nil
|
||||
@object_aspect_ids = []
|
||||
@all_aspects = current_user.aspects.fields(:name, :contacts)
|
||||
@aspects_dropdown_array = @all_aspects.collect{|x| [x.to_s, x.id]}
|
||||
@notification_count = Notification.for(current_user, :unread =>true).all.count
|
||||
end
|
||||
inflection_method :grammatical_gender => :gender
|
||||
|
||||
def ensure_http_referer_is_set
|
||||
request.env['HTTP_REFERER'] ||= '/aspects'
|
||||
end
|
||||
|
||||
def mobile_except_ipad
|
||||
if is_mobile_device?
|
||||
if request.env["HTTP_USER_AGENT"].include? "iPad"
|
||||
session[:mobile_view] = false
|
||||
else
|
||||
session[:mobile_view] = true
|
||||
def set_header_data
|
||||
if user_signed_in?
|
||||
if request.format.html?
|
||||
@aspect = nil
|
||||
@object_aspect_ids = []
|
||||
@notification_count = Notification.for(current_user, :unread =>true).count
|
||||
@unread_message_count = ConversationVisibility.sum(:unread, :conditions => "person_id = #{current_user.person.id}")
|
||||
end
|
||||
@all_aspects = current_user.aspects
|
||||
end
|
||||
end
|
||||
|
||||
def count_requests
|
||||
@request_count = Request.to(current_user.person).count if current_user
|
||||
@request_count = Request.where(:recipient_id => current_user.person.id).count if current_user
|
||||
end
|
||||
|
||||
def set_invites
|
||||
@@ -42,6 +44,23 @@ class ApplicationController < ActionController::Base
|
||||
end
|
||||
end
|
||||
|
||||
def set_git_header
|
||||
headers['X-Git-Update'] = AppConfig[:git_update]
|
||||
headers['X-Git-Revision'] = AppConfig[:git_revision]
|
||||
end
|
||||
|
||||
def which_action_and_user
|
||||
str = "event=request_with_user controller=#{self.class} action=#{self.action_name} "
|
||||
if current_user
|
||||
str << "uid=#{current_user.id} "
|
||||
str << "user_created_at='#{current_user.created_at.to_date.to_s}' user_created_at_unix=#{current_user.created_at.to_i} " if current_user.created_at
|
||||
str << "user_non_pending_contact_count=#{current_user.contacts.size} user_contact_count=#{Contact.unscoped.where(:user_id => current_user.id).size} "
|
||||
else
|
||||
str << 'uid=nil'
|
||||
end
|
||||
Rails.logger.info str
|
||||
end
|
||||
|
||||
def set_locale
|
||||
if user_signed_in?
|
||||
I18n.locale = current_user.language
|
||||
@@ -49,25 +68,36 @@ class ApplicationController < ActionController::Base
|
||||
I18n.locale = request.compatible_language_from AVAILABLE_LANGUAGE_CODES
|
||||
end
|
||||
end
|
||||
def clear_gc_stats
|
||||
GC.clear_stats if GC.respond_to?(:clear_stats)
|
||||
end
|
||||
|
||||
def similar_people contact, opts={}
|
||||
opts[:limit] ||= 5
|
||||
aspect_ids = contact.aspect_ids
|
||||
count = Contact.count(:user_id => current_user.id,
|
||||
:person_id.ne => contact.person.id,
|
||||
:aspect_ids.in => aspect_ids)
|
||||
|
||||
if count > opts[:limit]
|
||||
offset = rand(count-opts[:limit])
|
||||
else
|
||||
offset = 0
|
||||
def redirect_unless_admin
|
||||
admins = AppConfig[:admins]
|
||||
unless admins.present? && admins.include?(current_user.username)
|
||||
redirect_to root_url
|
||||
end
|
||||
end
|
||||
|
||||
contacts = Contact.all(:user_id => current_user.id,
|
||||
:person_id.ne => contact.person.id,
|
||||
:aspect_ids.in => aspect_ids,
|
||||
:skip => offset,
|
||||
:limit => opts[:limit])
|
||||
contacts.collect!{ |contact| contact.person }
|
||||
def set_grammatical_gender
|
||||
if (user_signed_in? && I18n.inflector.inflected_locale?)
|
||||
gender = current_user.profile.gender.to_s.tr('!()[]"\'`*=|/\#.,-:', '').downcase
|
||||
unless gender.empty?
|
||||
i_langs = I18n.inflector.inflected_locales(:gender)
|
||||
i_langs.delete I18n.locale
|
||||
i_langs.unshift I18n.locale
|
||||
i_langs.each do |lang|
|
||||
token = I18n.inflector.true_token(gender, :gender, lang)
|
||||
unless token.nil?
|
||||
@grammatical_gender = token
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def grammatical_gender
|
||||
@grammatical_gender || nil
|
||||
end
|
||||
end
|
||||
|
||||
67
app/controllers/aspect_memberships_controller.rb
Normal file
67
app/controllers/aspect_memberships_controller.rb
Normal file
@@ -0,0 +1,67 @@
|
||||
# Copyright (c) 2010, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
#
|
||||
|
||||
class AspectMembershipsController < ApplicationController
|
||||
before_filter :authenticate_user!
|
||||
|
||||
def destroy
|
||||
#note :id is garbage
|
||||
|
||||
@person_id = params[:person_id]
|
||||
@aspect_id = params[:aspect_id]
|
||||
|
||||
@contact = current_user.contact_for(Person.where(:id => @person_id).first)
|
||||
membership = @contact ? @contact.aspect_memberships.where(:aspect_id => @aspect_id).first : nil
|
||||
|
||||
if membership && membership.destroy
|
||||
flash.now[:notice] = I18n.t 'aspect_memberships.destroy.success'
|
||||
|
||||
respond_to do |format|
|
||||
format.js do
|
||||
render :json => {:button_html =>
|
||||
render_to_string(:partial => 'aspect_memberships/remove_from_aspect',
|
||||
:locals => {:aspect => membership.aspect,
|
||||
:person => @contact.person,
|
||||
:contact => @contact }),
|
||||
:aspect_id => @aspect_id}
|
||||
end
|
||||
format.html{
|
||||
redirect_to :back
|
||||
}
|
||||
end
|
||||
else
|
||||
flash.now[:error] = I18n.t 'aspect_memberships.destroy.failure'
|
||||
errors = membership ? membership.errors.full_messages : t('aspect_memberships.destroy.no_membership')
|
||||
respond_to do |format|
|
||||
format.js { render :text => errors, :status => 403 }
|
||||
format.html{
|
||||
redirect_to :back
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
@person = Person.find(params[:person_id])
|
||||
@aspect = current_user.aspects.where(:id => params[:aspect_id]).first
|
||||
@contact = current_user.contact_for(@person)
|
||||
|
||||
current_user.add_contact_to_aspect(@contact, @aspect)
|
||||
|
||||
flash.now[:notice] = I18n.t 'aspects.add_to_aspect.success'
|
||||
|
||||
respond_to do |format|
|
||||
format.js { render :json => {
|
||||
:button_html => render_to_string(:partial => 'aspect_memberships/add_to_aspect',
|
||||
:locals => {:aspect_id => @aspect.id,
|
||||
:person_id => @person.id}),
|
||||
:badge_html => render_to_string(:partial => 'aspects/aspect_badge',
|
||||
:locals => {:aspect => @aspect})
|
||||
}}
|
||||
format.html{ redirect_to aspect_path(@aspect.id)}
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -6,44 +6,67 @@ class AspectsController < ApplicationController
|
||||
before_filter :authenticate_user!
|
||||
|
||||
respond_to :html
|
||||
respond_to :json, :only => :show
|
||||
respond_to :json, :only => [:show, :create]
|
||||
respond_to :js
|
||||
|
||||
def index
|
||||
if params[:a_ids]
|
||||
@aspects = current_user.aspects_from_ids(params[:a_ids])
|
||||
@aspects = current_user.aspects.where(:id => params[:a_ids]).includes(:contacts => {:person => :profile})
|
||||
else
|
||||
@aspects = current_user.aspects
|
||||
@aspects = current_user.aspects.includes(:contacts => {:person => :profile})
|
||||
end
|
||||
@selected_contacts = @aspects.inject([]){|arr, aspect| arr.concat(aspect.contacts)}
|
||||
@selected_contacts.uniq!
|
||||
|
||||
# redirect to signup
|
||||
if current_user.getting_started == true || @aspects.blank?
|
||||
if (current_user.getting_started == true || @aspects.blank?) && !request.format.mobile?
|
||||
redirect_to getting_started_path
|
||||
else
|
||||
|
||||
if params[:sort_order].blank? and session[:sort_order].blank?
|
||||
session[:sort_order] = 'updated_at'
|
||||
elsif not params[:sort_order].blank? and not session[:sort_order] == params[:sort_order]
|
||||
session[:sort_order] = params[:sort_order] == 'created_at' ? 'created_at' : 'updated_at'
|
||||
end
|
||||
sort_order = session[:sort_order] == 'created_at' ? 'created_at' : 'updated_at'
|
||||
@aspect_ids = @aspects.map{|a| a.id}
|
||||
post_ids = @aspects.map{|a| a.post_ids}.flatten!
|
||||
|
||||
@posts = Post.where(:id.in => post_ids, :_type => "StatusMessage").paginate :page => params[:page], :per_page => 15, :order => 'created_at DESC'
|
||||
@post_hashes = hashes_for_posts @posts
|
||||
@posts = StatusMessage.joins(:aspects).where(:pending => false,
|
||||
:aspects => {:id => @aspect_ids}).includes(:comments, :photos).select('DISTINCT `posts`.*').paginate(
|
||||
:page => params[:page], :per_page => 15, :order => sort_order + ' DESC')
|
||||
@fakes = PostsFake.new(@posts)
|
||||
|
||||
@contacts = Contact.all(:aspect_ids.in => @aspect_ids, :user_id => current_user.id, :pending => false)
|
||||
@contact_hashes = hashes_for_contacts @contacts
|
||||
@aspect_hashes = hashes_for_aspects @aspects, @contacts, :limit => 16
|
||||
@contact_count = current_user.contacts.count
|
||||
|
||||
@aspect = :all unless params[:a_ids]
|
||||
@aspect ||= @aspects.first #used in mobile
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
@aspect = current_user.aspects.create(params[:aspect])
|
||||
#hack, we don't know why mass assignment is not working
|
||||
@aspect.contacts_visible = params[:aspect][:contacts_visible]
|
||||
@aspect.save
|
||||
|
||||
if @aspect.valid?
|
||||
flash[:notice] = I18n.t('aspects.create.success', :name => @aspect.name)
|
||||
if current_user.getting_started
|
||||
redirect_to :back
|
||||
elsif request.env['HTTP_REFERER'].include?("aspects/manage")
|
||||
redirect_to :back
|
||||
elsif params[:aspect][:share_with]
|
||||
@contact = Contact.where(:id => params[:aspect][:contact_id]).first
|
||||
@person = Person.where(:id => params[:aspect][:person_id]).first
|
||||
@contact = current_user.contact_for(@person) || Contact.new
|
||||
|
||||
respond_to do |format|
|
||||
format.js { render :json => {:html => render_to_string(
|
||||
:partial => 'aspects/aspect_list_item',
|
||||
:locals => {:aspect => @aspect,
|
||||
:person => @person,
|
||||
:contact => @contact}
|
||||
), :aspect_id => @aspect.id},:status => 201 }
|
||||
end
|
||||
else
|
||||
respond_with @aspect
|
||||
end
|
||||
@@ -58,194 +81,90 @@ class AspectsController < ApplicationController
|
||||
end
|
||||
|
||||
def destroy
|
||||
@aspect = current_user.aspect_by_id params[:id]
|
||||
@aspect = current_user.aspects.where(:id => params[:id]).first
|
||||
|
||||
begin
|
||||
current_user.drop_aspect @aspect
|
||||
flash[:notice] = I18n.t 'aspects.destroy.success',:name => @aspect.name
|
||||
redirect_to :back
|
||||
rescue RuntimeError => e
|
||||
flash[:error] = e.message
|
||||
redirect_to :back
|
||||
redirect_to aspects_path
|
||||
rescue ActiveRecord::StatementInvalid => e
|
||||
flash[:error] = I18n.t 'aspects.destroy.failure',:name => @aspect.name
|
||||
redirect_to aspects_path
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
@aspect = current_user.aspect_by_id params[:id]
|
||||
@contacts = current_user.contacts.where(:pending => false)
|
||||
unless @aspect
|
||||
render :file => "#{Rails.root}/public/404.html", :layout => false, :status => 404
|
||||
else
|
||||
@aspect_ids = [@aspect.id]
|
||||
@aspect_contacts = hashes_for_contacts Contact.all(:user_id => current_user.id, :aspect_ids.in => [@aspect.id], :pending => false)
|
||||
@aspect_contacts_count = @aspect_contacts.count
|
||||
|
||||
@all_contacts = hashes_for_contacts @contacts
|
||||
|
||||
@posts = @aspect.posts.find_all_by__type("StatusMessage", :order => 'created_at desc').paginate :page => params[:page], :per_page => 15
|
||||
@post_hashes = hashes_for_posts @posts
|
||||
@post_count = @posts.count
|
||||
|
||||
@aspect = current_user.aspects.where(:id => params[:id]).first
|
||||
if @aspect
|
||||
redirect_to aspects_path('a_ids[]' => @aspect.id)
|
||||
else
|
||||
redirect_to aspects_path
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@aspect = current_user.aspect_by_id params[:id]
|
||||
@contacts = current_user.contacts.where(:pending => false)
|
||||
@aspect = current_user.aspects.where(:id => params[:id]).includes(:contacts => {:person => :profile}).first
|
||||
@contacts = current_user.contacts.includes(:person => :profile)
|
||||
unless @aspect
|
||||
render :file => "#{Rails.root}/public/404.html", :layout => false, :status => 404
|
||||
else
|
||||
@aspect_ids = [@aspect.id]
|
||||
@aspect_contacts = hashes_for_contacts Contact.all(:user_id => current_user.id, :aspect_ids.in => [@aspect.id], :pending => false)
|
||||
@aspect_contacts_count = @aspect_contacts.count
|
||||
|
||||
@all_contacts = hashes_for_contacts @contacts
|
||||
|
||||
@aspect_contacts_count = @aspect.contacts.length
|
||||
render :layout => false
|
||||
end
|
||||
end
|
||||
|
||||
def manage
|
||||
@aspect = :manage
|
||||
@contacts = current_user.contacts.where(:pending => false)
|
||||
@remote_requests = Request.hashes_for_person(current_user.person)
|
||||
@aspect_hashes = hashes_for_aspects @all_aspects, @contacts
|
||||
@contacts = current_user.contacts.includes(:person => :profile)
|
||||
@remote_requests = Request.where(:recipient_id => current_user.person.id).includes(:sender => :profile)
|
||||
@aspects = @all_aspects.includes(:contacts => {:person => :profile})
|
||||
end
|
||||
|
||||
def update
|
||||
@aspect = current_user.aspect_by_id(params[:id])
|
||||
if @aspect.update_attributes( params[:aspect] )
|
||||
@aspect = current_user.aspects.where(:id => params[:id]).first
|
||||
|
||||
if @aspect.update_attributes!( params[:aspect] )
|
||||
#hack, we don't know why mass assignment is not working
|
||||
@aspect.contacts_visible = params[:aspect][:contacts_visible]
|
||||
@aspect.save
|
||||
flash[:notice] = I18n.t 'aspects.update.success',:name => @aspect.name
|
||||
else
|
||||
flash[:error] = I18n.t 'aspects.update.failure',:name => @aspect.name
|
||||
end
|
||||
|
||||
respond_with @aspect
|
||||
end
|
||||
|
||||
def toggle_contact_visibility
|
||||
@aspect = current_user.aspects.where(:id => params[:aspect_id]).first
|
||||
|
||||
if @aspect.contacts_visible?
|
||||
@aspect.contacts_visible = false
|
||||
else
|
||||
@aspect.contacts_visible = true
|
||||
end
|
||||
@aspect.save
|
||||
end
|
||||
|
||||
def move_contact
|
||||
@person = Person.find(params[:person_id])
|
||||
@from_aspect = current_user.aspects.find(params[:from])
|
||||
@to_aspect = current_user.aspects.find(params[:to][:to])
|
||||
@from_aspect = current_user.aspects.where(:id => params[:from]).first
|
||||
@to_aspect = current_user.aspects.where(:id => params[:to][:to]).first
|
||||
|
||||
response_hash = { }
|
||||
|
||||
unless current_user.move_contact( @person, @to_aspect, @from_aspect)
|
||||
flash[:error] = I18n.t 'aspects.move_contact.error',:inspect => params.inspect
|
||||
end
|
||||
if aspect = current_user.aspect_by_id(params[:to][:to])
|
||||
flash[:notice] = I18n.t 'aspects.move_contact.success'
|
||||
render :nothing => true
|
||||
if aspect = current_user.aspects.where(:id => params[:to][:to]).first
|
||||
response_hash[:notice] = I18n.t 'aspects.move_contact.success'
|
||||
response_hash[:success] = true
|
||||
else
|
||||
flash[:notice] = I18n.t 'aspects.move_contact.failure'
|
||||
render aspects_manage_path
|
||||
response_hash[:notice] = I18n.t 'aspects.move_contact.failure'
|
||||
response_hash[:success] = false
|
||||
end
|
||||
end
|
||||
|
||||
def add_to_aspect
|
||||
@person = Person.find(params[:person_id])
|
||||
@aspect = current_user.aspects.find(params[:aspect_id])
|
||||
@contact = current_user.contact_for(@person)
|
||||
|
||||
if @contact
|
||||
current_user.add_contact_to_aspect(@contact, @aspect)
|
||||
else
|
||||
current_user.send_contact_request_to(@person, @aspect)
|
||||
contact = current_user.contact_for(@person)
|
||||
|
||||
if request = Request.from(@person).to(current_user).first
|
||||
request.destroy
|
||||
contact.update_attributes(:pending => false)
|
||||
end
|
||||
end
|
||||
flash.now[:notice] = I18n.t 'aspects.add_to_aspect.success'
|
||||
|
||||
respond_to do |format|
|
||||
format.js { render :json => {
|
||||
:button_html => render_to_string(:partial => 'aspects/add_to_aspect',
|
||||
:locals => {:aspect_id => @aspect.id,
|
||||
:person_id => @person.id}),
|
||||
:badge_html => render_to_string(:partial => 'aspects/aspect_badge',
|
||||
:locals => {:aspect => @aspect})
|
||||
}}
|
||||
format.html{ redirect_to aspect_path(@aspect.id)}
|
||||
end
|
||||
end
|
||||
|
||||
def remove_from_aspect
|
||||
begin current_user.delete_person_from_aspect(params[:person_id], params[:aspect_id])
|
||||
@person_id = params[:person_id]
|
||||
@aspect_id = params[:aspect_id]
|
||||
flash.now[:notice] = I18n.t 'aspects.remove_from_aspect.success'
|
||||
|
||||
respond_to do |format|
|
||||
format.js { render :json => {:button_html =>
|
||||
render_to_string(:partial => 'aspects/remove_from_aspect',
|
||||
:locals => {:aspect_id => @aspect_id,
|
||||
:person_id => @person_id}),
|
||||
:aspect_id => @aspect_id
|
||||
}}
|
||||
format.html{
|
||||
redirect_to :back
|
||||
}
|
||||
end
|
||||
rescue Exception => e
|
||||
flash.now[:error] = I18n.t 'aspects.remove_from_aspect.failure'
|
||||
|
||||
respond_to do |format|
|
||||
format.js { render :text => e, :status => 403 }
|
||||
format.html{
|
||||
redirect_to :back
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def hashes_for_contacts contacts
|
||||
people = Person.all(:id.in => contacts.map{|c| c.person_id}, :fields => [:profile, :diaspora_handle])
|
||||
people_hash = {}
|
||||
people.each{|p| people_hash[p.id] = p}
|
||||
contacts.map{|c| {:contact => c, :person => people_hash[c.person_id.to_id]}}
|
||||
end
|
||||
|
||||
def hashes_for_aspects aspects, contacts, opts = {}
|
||||
contact_hashes = hashes_for_contacts contacts
|
||||
aspects.map do |a|
|
||||
hash = {:aspect => a}
|
||||
aspect_contact_hashes = contact_hashes.select{|c|
|
||||
c[:contact].aspect_ids.include?(a.id)}
|
||||
hash[:contact_count] = aspect_contact_hashes.count
|
||||
if opts[:limit]
|
||||
hash[:contacts] = aspect_contact_hashes.slice(0,opts[:limit])
|
||||
else
|
||||
hash[:contacts] = aspect_contact_hashes
|
||||
end
|
||||
hash
|
||||
end
|
||||
end
|
||||
def hashes_for_posts posts
|
||||
post_ids = []
|
||||
post_person_ids = []
|
||||
posts.each{|p| post_ids << p.id; post_person_ids << p.person_id}
|
||||
|
||||
comment_hash = Comment.hash_from_post_ids post_ids
|
||||
commenters_hash = Person.from_post_comment_hash comment_hash
|
||||
photo_hash = Photo.hash_from_post_ids post_ids
|
||||
|
||||
post_person_ids.uniq!
|
||||
posters = Person.all(:id.in => post_person_ids, :fields => [:profile, :owner_id, :diaspora_handle])
|
||||
posters_hash = {}
|
||||
posters.each{|poster| posters_hash[poster.id] = poster}
|
||||
|
||||
posts.map do |post|
|
||||
{:post => post,
|
||||
:photos => photo_hash[post.id],
|
||||
:person => posters_hash[post.person_id],
|
||||
:comments => comment_hash[post.id].map do |comment|
|
||||
{:comment => comment,
|
||||
:person => commenters_hash[comment.person_id],
|
||||
}
|
||||
end,
|
||||
}
|
||||
end
|
||||
render :text => response_hash.to_json
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,35 +6,38 @@ class CommentsController < ApplicationController
|
||||
include ApplicationHelper
|
||||
before_filter :authenticate_user!
|
||||
|
||||
respond_to :html
|
||||
respond_to :html, :mobile
|
||||
respond_to :json, :only => :show
|
||||
|
||||
def create
|
||||
target = current_user.find_visible_post_by_id params[:post_id]
|
||||
text = params[:text]
|
||||
|
||||
@comment = current_user.build_comment(text, :on => target)
|
||||
if target
|
||||
@comment = current_user.build_comment(text, :on => target)
|
||||
|
||||
if @comment.save(:safe => true)
|
||||
raise 'MongoMapper failed to catch a failed save' unless @comment.id
|
||||
Rails.logger.info("event=comment_create user=#{current_user.diaspora_handle} status=success comment=#{@comment.id}")
|
||||
current_user.dispatch_comment(@comment)
|
||||
if @comment.save
|
||||
Rails.logger.info("event=create type=comment user=#{current_user.diaspora_handle} status=success comment=#{@comment.id} chars=#{params[:text].length}")
|
||||
Postzord::Dispatch.new(current_user, @comment).post
|
||||
|
||||
respond_to do |format|
|
||||
format.js{
|
||||
json = { :post_id => @comment.post_id,
|
||||
:comment_id => @comment.id,
|
||||
:html => render_to_string(
|
||||
:partial => 'comments/comment',
|
||||
:locals => { :hash => {
|
||||
:comment => @comment,
|
||||
:person => current_user.person,
|
||||
}}
|
||||
)
|
||||
}
|
||||
render(:json => json, :status => 201)
|
||||
}
|
||||
format.html{ render :nothing => true, :status => 201 }
|
||||
respond_to do |format|
|
||||
format.js{
|
||||
json = { :post_id => @comment.post_id,
|
||||
:comment_id => @comment.id,
|
||||
:html => render_to_string(
|
||||
:partial => 'comments/comment',
|
||||
:locals => { :comment => @comment,
|
||||
:person => current_user.person,
|
||||
}
|
||||
)
|
||||
}
|
||||
render(:json => json, :status => 201)
|
||||
}
|
||||
format.html{ render :nothing => true, :status => 201 }
|
||||
format.mobile{ redirect_to status_message_path(@comment.post_id) }
|
||||
end
|
||||
else
|
||||
render :nothing => true, :status => 406
|
||||
end
|
||||
else
|
||||
render :nothing => true, :status => 406
|
||||
|
||||
79
app/controllers/contacts_controller.rb
Normal file
79
app/controllers/contacts_controller.rb
Normal file
@@ -0,0 +1,79 @@
|
||||
# Copyright (c) 2010, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class ContactsController < ApplicationController
|
||||
before_filter :authenticate_user!
|
||||
|
||||
def new
|
||||
@person = Person.find(params[:person_id])
|
||||
@aspects_with_person = []
|
||||
@aspects_without_person = current_user.aspects
|
||||
@contact = Contact.new
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
def create
|
||||
@person = Person.find(params[:person_id])
|
||||
@aspect = current_user.aspects.where(:id => params[:aspect_id]).first
|
||||
|
||||
@contact = request_to_aspect(@aspect, @person)
|
||||
|
||||
if @contact && @contact.persisted?
|
||||
flash.now[:notice] = I18n.t 'aspects.add_to_aspect.success'
|
||||
|
||||
respond_to do |format|
|
||||
format.js { render :json => {
|
||||
:button_html => render_to_string(:partial => 'aspect_memberships/add_to_aspect',
|
||||
:locals => {:aspect_id => @aspect.id,
|
||||
:person_id => @person.id}),
|
||||
:badge_html => render_to_string(:partial => 'aspects/aspect_badge',
|
||||
:locals => {:aspect => @aspect}),
|
||||
:contact_id => @contact.id
|
||||
}}
|
||||
format.html{ redirect_to aspect_path(@aspect.id)}
|
||||
end
|
||||
else
|
||||
flash[:error] = I18n.t 'contacts.create.failure'
|
||||
redirect_to :back
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@all_aspects ||= current_user.aspects
|
||||
@contact = Contact.unscoped.where(:id => params[:id], :user_id => current_user.id).first
|
||||
|
||||
@person = @contact.person
|
||||
@aspects_with_person = []
|
||||
|
||||
if @contact
|
||||
@aspects_with_person = @contact.aspects
|
||||
end
|
||||
|
||||
@aspects_without_person = @all_aspects - @aspects_with_person
|
||||
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
def destroy
|
||||
contact = Contact.unscoped.where(:id => params[:id], :user_id => current_user.id).first
|
||||
if current_user.disconnect(contact)
|
||||
flash[:notice] = I18n.t('contacts.destroy.success', :name => contact.person.name)
|
||||
else
|
||||
flash[:error] = I18n.t('contacts.destroy.failure', :name => contact.person.name)
|
||||
end
|
||||
redirect_to contact.person
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def request_to_aspect(aspect, person)
|
||||
current_user.send_contact_request_to(person, aspect)
|
||||
contact = current_user.contact_for(person)
|
||||
if request = Request.where(:sender_id => person.id, :recipient_id => current_user.person.id).first
|
||||
request.destroy
|
||||
contact.update_attributes(:pending => false)
|
||||
end
|
||||
contact
|
||||
end
|
||||
end
|
||||
19
app/controllers/conversation_visibilities_controller.rb
Normal file
19
app/controllers/conversation_visibilities_controller.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
# Copyright (c) 2010, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
#
|
||||
|
||||
class ConversationVisibilitiesController < ApplicationController
|
||||
before_filter :authenticate_user!
|
||||
|
||||
def destroy
|
||||
@vis = ConversationVisibility.where(:person_id => current_user.person.id,
|
||||
:conversation_id => params[:conversation_id]).first
|
||||
if @vis
|
||||
if @vis.destroy
|
||||
flash[:notice] = "Conversation successfully removed"
|
||||
end
|
||||
end
|
||||
redirect_to conversations_path
|
||||
end
|
||||
end
|
||||
66
app/controllers/conversations_controller.rb
Normal file
66
app/controllers/conversations_controller.rb
Normal file
@@ -0,0 +1,66 @@
|
||||
class ConversationsController < ApplicationController
|
||||
before_filter :authenticate_user!
|
||||
|
||||
respond_to :html, :json
|
||||
|
||||
def index
|
||||
@conversations = Conversation.joins(:conversation_visibilities).where(
|
||||
:conversation_visibilities => {:person_id => current_user.person.id}).paginate(
|
||||
:page => params[:page], :per_page => 15, :order => 'updated_at DESC')
|
||||
|
||||
@visibilities = ConversationVisibility.where( :person_id => current_user.person.id ).paginate(
|
||||
:page => params[:page], :per_page => 15, :order => 'updated_at DESC')
|
||||
|
||||
@unread_counts = {}
|
||||
@visibilities.each{|v| @unread_counts[v.conversation_id] = v.unread}
|
||||
|
||||
@authors = {}
|
||||
@conversations.each{|c| @authors[c.id] = c.last_author}
|
||||
|
||||
@conversation = Conversation.joins(:conversation_visibilities).where(
|
||||
:conversation_visibilities => {:person_id => current_user.person.id, :conversation_id => params[:conversation_id]}).first
|
||||
end
|
||||
|
||||
def create
|
||||
person_ids = Contact.where(:id => params[:contact_ids].split(',')).map! do |contact|
|
||||
contact.person_id
|
||||
end
|
||||
|
||||
params[:conversation][:participant_ids] = person_ids | [current_user.person.id]
|
||||
params[:conversation][:author] = current_user.person
|
||||
|
||||
if @conversation = Conversation.create(params[:conversation])
|
||||
Postzord::Dispatch.new(current_user, @conversation).post
|
||||
|
||||
flash[:notice] = "Message sent"
|
||||
if params[:profile]
|
||||
redirect_to person_path(params[:profile])
|
||||
else
|
||||
redirect_to conversations_path(:conversation_id => @conversation.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
@conversation = Conversation.joins(:conversation_visibilities).where(:id => params[:id],
|
||||
:conversation_visibilities => {:person_id => current_user.person.id}).first
|
||||
|
||||
if @visibility = ConversationVisibility.where(:conversation_id => params[:id], :person_id => current_user.person.id).first
|
||||
@visibility.unread = 0
|
||||
@visibility.save
|
||||
end
|
||||
|
||||
if @conversation
|
||||
render :layout => false
|
||||
else
|
||||
redirect_to conversations_path
|
||||
end
|
||||
end
|
||||
|
||||
def new
|
||||
@all_contacts_and_ids = current_user.contacts.map{|c| {:value => c.id, :name => c.person.name}}
|
||||
@contact = current_user.contacts.find(params[:contact_id]) if params[:contact_id]
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
end
|
||||
@@ -6,11 +6,25 @@ class HomeController < ApplicationController
|
||||
|
||||
def show
|
||||
if current_user
|
||||
redirect_to aspects_path
|
||||
if params[:home]
|
||||
redirect_to :controller => 'aspects', :action => 'index'
|
||||
else
|
||||
redirect_to :controller => 'aspects', :action => 'index', :a_ids => current_user.aspects.where(:open => true).select(:id).all
|
||||
end
|
||||
elsif is_mobile_device?
|
||||
redirect_to user_session_path
|
||||
else
|
||||
@landing_page = true
|
||||
render :show
|
||||
end
|
||||
end
|
||||
|
||||
def toggle_mobile
|
||||
if session[:mobile_view]
|
||||
session[:mobile_view] = false
|
||||
else
|
||||
session[:mobile_view] = true
|
||||
end
|
||||
redirect_to :back
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,8 +7,8 @@ class InvitationsController < Devise::InvitationsController
|
||||
before_filter :check_token, :only => [:edit]
|
||||
|
||||
def new
|
||||
sent_invitations = current_user.invitations_from_me.fields(:to_id).all
|
||||
@emails_delivered = sent_invitations.map!{ |i| i.to.email }
|
||||
@sent_invitations = current_user.invitations_from_me.includes(:recipient)
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
def create
|
||||
@@ -23,7 +23,7 @@ class InvitationsController < Devise::InvitationsController
|
||||
|
||||
good_emails, bad_emails = emails.partition{|e| e.try(:match, Devise.email_regexp)}
|
||||
|
||||
good_emails.each{|e| Resque.enqueue(Jobs::InviteUser, current_user.id, e, aspect, message)}
|
||||
good_emails.each{|e| Resque.enqueue(Job::InviteUserByEmail, current_user.id, e, aspect, message)}
|
||||
|
||||
if bad_emails.any?
|
||||
flash[:error] = I18n.t('invitations.create.sent') + good_emails.join(', ') + " "+ I18n.t('invitations.create.rejected') + bad_emails.join(', ')
|
||||
@@ -41,11 +41,14 @@ class InvitationsController < Devise::InvitationsController
|
||||
raise I18n.t('invitations.check_token.not_found')
|
||||
end
|
||||
user = User.find_by_invitation_token(params[:user][:invitation_token])
|
||||
user.seed_aspects
|
||||
user.accept_invitation!(params[:user])
|
||||
user.seed_aspects
|
||||
rescue Exception => e
|
||||
user = nil
|
||||
flash[:error] = e.message
|
||||
record = e.record
|
||||
record.errors.delete(:person)
|
||||
|
||||
flash[:error] = record.errors.full_messages.join(", ")
|
||||
end
|
||||
|
||||
if user
|
||||
@@ -57,6 +60,15 @@ class InvitationsController < Devise::InvitationsController
|
||||
end
|
||||
end
|
||||
|
||||
def resend
|
||||
invitation = current_user.invitations_from_me.where(:id => params[:id]).first
|
||||
if invitation
|
||||
Resque.enqueue(Job::ResendInvitation, invitation.id)
|
||||
flash[:notice] = I18n.t('invitations.create.sent') + invitation.recipient.email
|
||||
end
|
||||
redirect_to :back
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def check_token
|
||||
|
||||
32
app/controllers/messages_controller.rb
Normal file
32
app/controllers/messages_controller.rb
Normal file
@@ -0,0 +1,32 @@
|
||||
# Copyright (c) 2010, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class MessagesController < ApplicationController
|
||||
include ApplicationHelper
|
||||
before_filter :authenticate_user!
|
||||
|
||||
respond_to :html, :mobile
|
||||
respond_to :json, :only => :show
|
||||
|
||||
def create
|
||||
cnv = Conversation.joins(:conversation_visibilities).where(:id => params[:conversation_id],
|
||||
:conversation_visibilities => {:person_id => current_user.person.id}).first
|
||||
|
||||
if cnv
|
||||
message = Message.new(:conversation_id => cnv.id, :text => params[:message][:text], :author => current_user.person)
|
||||
|
||||
if message.save
|
||||
Rails.logger.info("event=create type=comment user=#{current_user.diaspora_handle} status=success message=#{message.id} chars=#{params[:message][:text].length}")
|
||||
Postzord::Dispatch.new(current_user, message).post
|
||||
|
||||
redirect_to conversations_path(:conversation_id => cnv.id)
|
||||
else
|
||||
render :nothing => true, :status => 406
|
||||
end
|
||||
else
|
||||
render :nothing => true, :status => 406
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -4,11 +4,11 @@
|
||||
|
||||
class NotificationsController < ApplicationController
|
||||
before_filter :authenticate_user!
|
||||
respond_to :html
|
||||
respond_to :html, :json
|
||||
|
||||
|
||||
def update
|
||||
note = Notification.find_by_user_id_and_id(current_user.id, params[:id])
|
||||
note = Notification.where(:recipient_id => current_user.id, :id => params[:id]).first
|
||||
if note
|
||||
note.update_attributes(:unread => false)
|
||||
render :nothing => true
|
||||
@@ -18,8 +18,14 @@ class NotificationsController < ApplicationController
|
||||
end
|
||||
|
||||
def index
|
||||
@notifications = Notification.for(current_user).paginate :page => params[:page], :per_page => 25
|
||||
@group_days = @notifications.group_by{|note| note.created_at.strftime("%B %d") }
|
||||
@notifications = Notification.find(:all, :conditions => {:recipient_id => current_user.id},
|
||||
:order => 'created_at desc', :include => [:target, {:actors => :profile}]).paginate :page => params[:page], :per_page => 25
|
||||
@group_days = @notifications.group_by{|note| I18n.l(note.updated_at, :format => I18n.t('date.formats.fullmonth_day')) }
|
||||
respond_with @notifications
|
||||
end
|
||||
|
||||
def read_all
|
||||
Notification.where(:recipient_id => current_user.id).update_all(:unread => false)
|
||||
redirect_to aspects_path
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,36 +3,37 @@
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class PeopleController < ApplicationController
|
||||
before_filter :authenticate_user!
|
||||
before_filter :authenticate_user!, :except => [:show]
|
||||
|
||||
respond_to :html
|
||||
respond_to :json, :only => [:index, :show]
|
||||
|
||||
def index
|
||||
@aspect = :search
|
||||
params[:q] ||= params[:term]
|
||||
limit = params[:limit] || 15
|
||||
|
||||
@people = Person.search(params[:q]).paginate :page => params[:page], :per_page => 15, :order => 'created_at DESC'
|
||||
if @people.count == 1
|
||||
redirect_to @people.first
|
||||
else
|
||||
@hashes = hashes_for_people(@people, @aspects)
|
||||
#only do it if it is an email address
|
||||
if params[:q].try(:match, Devise.email_regexp)
|
||||
webfinger(params[:q])
|
||||
end
|
||||
@people = Person.search(params[:q], current_user).paginate :page => params[:page], :per_page => limit
|
||||
@hashes = hashes_for_people(@people, @aspects) unless request.format == :json
|
||||
|
||||
#only do it if it is an email address
|
||||
if params[:q].try(:match, Devise.email_regexp)
|
||||
webfinger(params[:q])
|
||||
end
|
||||
respond_with @people
|
||||
end
|
||||
|
||||
def hashes_for_people people, aspects
|
||||
ids = people.map{|p| p.id}
|
||||
requests = {}
|
||||
Request.all(:from_id.in => ids, :to_id => current_user.person.id).each do |r|
|
||||
requests[r.to_id] = r
|
||||
Request.where(:sender_id => ids, :recipient_id => current_user.person.id).each do |r|
|
||||
requests[r.id] = r
|
||||
end
|
||||
contacts = {}
|
||||
Contact.all(:user_id => current_user.id, :person_id.in => ids).each do |contact|
|
||||
Contact.unscoped.where(:user_id => current_user.id, :person_id => ids).each do |contact|
|
||||
contacts[contact.person_id] = contact
|
||||
end
|
||||
|
||||
people.map{|p|
|
||||
{:person => p,
|
||||
:contact => contacts[p.id],
|
||||
@@ -42,30 +43,38 @@ class PeopleController < ApplicationController
|
||||
end
|
||||
|
||||
def show
|
||||
@person = Person.find(params[:id].to_id)
|
||||
@person = Person.where(:id => params[:id]).first
|
||||
@post_type = :all
|
||||
@share_with = (params[:share_with] == 'true')
|
||||
|
||||
if @person
|
||||
@incoming_request = Request.to(current_user).from(@person).first
|
||||
|
||||
@profile = @person.profile
|
||||
@contact = current_user.contact_for(@person)
|
||||
@aspects_with_person = []
|
||||
|
||||
if @contact
|
||||
@aspects_with_person = @contact.aspects
|
||||
@similar_people = similar_people @contact
|
||||
end
|
||||
if current_user
|
||||
@incoming_request = current_user.request_from(@person)
|
||||
@contact = current_user.contact_for(@person)
|
||||
@aspects_with_person = []
|
||||
if @contact
|
||||
@aspects_with_person = @contact.aspects
|
||||
@contacts_of_contact = @contact.contacts
|
||||
else
|
||||
@contact ||= Contact.new
|
||||
@contacts_of_contact = []
|
||||
end
|
||||
|
||||
if (@person != current_user.person) && (!@contact || @contact.pending)
|
||||
@commenting_disabled = true
|
||||
if (@person != current_user.person) && (!@contact || @contact.pending)
|
||||
@commenting_disabled = true
|
||||
else
|
||||
@commenting_disabled = false
|
||||
end
|
||||
@posts = current_user.posts_from(@person).where(:type => "StatusMessage").paginate(:per_page => 15, :page => params[:page])
|
||||
else
|
||||
@commenting_disabled = false
|
||||
@commenting_disabled = true
|
||||
@posts = @person.posts.where(:type => "StatusMessage", :public => true).paginate(:per_page => 15, :page => params[:page], :order => 'created_at DESC')
|
||||
end
|
||||
|
||||
@posts = current_user.posts_from(@person).paginate :page => params[:page]
|
||||
@post_hashes = hashes_for_posts @posts
|
||||
|
||||
@fakes = PostsFake.new(@posts)
|
||||
respond_with @person, :locals => {:post_type => :all}
|
||||
|
||||
else
|
||||
@@ -74,36 +83,6 @@ class PeopleController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
current_user.disconnect(current_user.visible_person_by_id(params[:id]))
|
||||
redirect_to root_url
|
||||
end
|
||||
|
||||
def edit
|
||||
@aspect = :person_edit
|
||||
@person = current_user.person
|
||||
@profile = @person.profile
|
||||
end
|
||||
|
||||
def update
|
||||
# upload and set new profile photo
|
||||
params[:profile] ||= {}
|
||||
params[:profile][:searchable] ||= false
|
||||
params[:profile][:photo] = Photo.first(:person_id => current_user.person.id, :id => params[:photo_id]) if params[:photo_id]
|
||||
|
||||
if current_user.update_profile params[:profile]
|
||||
flash[:notice] = I18n.t 'people.update.updated'
|
||||
else
|
||||
flash[:error] = I18n.t 'people.update.failed'
|
||||
end
|
||||
|
||||
if params[:getting_started]
|
||||
redirect_to getting_started_path(:step => params[:getting_started].to_i+1)
|
||||
else
|
||||
redirect_to edit_person_path
|
||||
end
|
||||
end
|
||||
|
||||
def retrieve_remote
|
||||
if params[:diaspora_handle]
|
||||
webfinger(params[:diaspora_handle], :single_aspect_form => true)
|
||||
@@ -113,44 +92,8 @@ class PeopleController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def share_with
|
||||
@person = Person.find(params[:id].to_id)
|
||||
@contact = current_user.contact_for(@person)
|
||||
@aspects_with_person = []
|
||||
|
||||
if @contact
|
||||
@aspects_with_person = @contact.aspects
|
||||
end
|
||||
|
||||
@aspects_without_person = @all_aspects.reject do |aspect|
|
||||
@aspects_with_person.include?(aspect)
|
||||
end
|
||||
|
||||
render :layout => nil
|
||||
end
|
||||
|
||||
private
|
||||
def hashes_for_posts posts
|
||||
post_ids = posts.map{|p| p.id}
|
||||
comment_hash = Comment.hash_from_post_ids post_ids
|
||||
person_hash = Person.from_post_comment_hash comment_hash
|
||||
photo_hash = Photo.hash_from_post_ids post_ids
|
||||
|
||||
posts.map do |post|
|
||||
{:post => post,
|
||||
:person => @person,
|
||||
:photos => photo_hash[post.id],
|
||||
:comments => comment_hash[post.id].map do |comment|
|
||||
{:comment => comment,
|
||||
:person => person_hash[comment.person_id],
|
||||
}
|
||||
end,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def webfinger(account, opts = {})
|
||||
Resque.enqueue(Jobs::SocketWebfinger, current_user.id, account, opts)
|
||||
Resque.enqueue(Job::SocketWebfinger, current_user.id, account, opts)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -13,8 +13,8 @@ class PhotosController < ApplicationController
|
||||
@person = Person.find_by_id(params[:person_id])
|
||||
|
||||
if @person
|
||||
@incoming_request = Request.to(current_user).from(@person).first
|
||||
@outgoing_request = Request.from(current_user).to(@person).first
|
||||
@incoming_request = Request.where(:recipient_id => current_user.person.id, :sender_id => @person.id).first
|
||||
@outgoing_request = Request.where(:sender_id => current_user.person.id, :recipient_id => @person.id).first
|
||||
|
||||
@profile = @person.profile
|
||||
@contact = current_user.contact_for(@person)
|
||||
@@ -23,10 +23,15 @@ class PhotosController < ApplicationController
|
||||
|
||||
if @contact
|
||||
@aspects_with_person = @contact.aspects
|
||||
@similar_people = similar_people @contact
|
||||
@contacts_of_contact = @contact.contacts
|
||||
else
|
||||
@contact = Contact.new
|
||||
@contacts_of_contact = []
|
||||
end
|
||||
|
||||
@posts = current_user.raw_visible_posts.all(:_type => 'Photo', :person_id => @person.id, :order => 'created_at DESC').paginate :page => params[:page], :order => 'created_at DESC'
|
||||
@posts = current_user.visible_photos.where(
|
||||
:author_id => @person.id
|
||||
).paginate(:page => params[:page])
|
||||
|
||||
render 'people/show'
|
||||
|
||||
@@ -51,12 +56,13 @@ class PhotosController < ApplicationController
|
||||
@photo = current_user.build_post(:photo, params[:photo])
|
||||
|
||||
if @photo.save
|
||||
raise 'MongoMapper failed to catch a failed save' unless @photo.id
|
||||
|
||||
|
||||
aspects = current_user.aspects_from_ids(params[:photo][:aspect_ids])
|
||||
current_user.add_to_streams(@photo, aspects)
|
||||
current_user.dispatch_post(@photo, :to => params[:photo][:aspect_ids]) unless @photo.pending
|
||||
|
||||
unless @photo.pending
|
||||
current_user.add_to_streams(@photo, aspects)
|
||||
current_user.dispatch_post(@photo, :to => params[:photo][:aspect_ids])
|
||||
end
|
||||
|
||||
if params[:photo][:set_profile_photo]
|
||||
profile_params = {:image_url => @photo.url(:thumb_large),
|
||||
@@ -88,8 +94,8 @@ class PhotosController < ApplicationController
|
||||
end
|
||||
|
||||
def make_profile_photo
|
||||
person_id = current_user.person.id
|
||||
@photo = Photo.find_by_id_and_person_id(params[:photo_id], person_id)
|
||||
author_id = current_user.person.id
|
||||
@photo = Photo.where(:id => params[:photo_id], :author_id => author_id).first
|
||||
|
||||
if @photo
|
||||
profile_hash = {:image_url => @photo.url(:thumb_large),
|
||||
@@ -102,7 +108,7 @@ class PhotosController < ApplicationController
|
||||
:image_url => @photo.url(:thumb_large),
|
||||
:image_url_medium => @photo.url(:thumb_medium),
|
||||
:image_url_small => @photo.url(:thumb_small),
|
||||
:person_id => person_id},
|
||||
:author_id => author_id},
|
||||
:status => 201}
|
||||
end
|
||||
else
|
||||
@@ -114,7 +120,7 @@ class PhotosController < ApplicationController
|
||||
end
|
||||
|
||||
def destroy
|
||||
photo = current_user.my_posts.where(:_id => params[:id]).first
|
||||
photo = current_user.posts.where(:id => params[:id]).first
|
||||
|
||||
if photo
|
||||
photo.destroy
|
||||
@@ -133,7 +139,8 @@ class PhotosController < ApplicationController
|
||||
end
|
||||
|
||||
def show
|
||||
@photo = current_user.find_visible_post_by_id params[:id]
|
||||
@photo = current_user.visible_photos.where(:id => params[:id]).includes(:author, :status_message => :photos).first
|
||||
@photo ||= Photo.where(:public => true, :id => params[:id]).includes(:author, :status_message => :photos).first
|
||||
if @photo
|
||||
@parent = @photo.status_message
|
||||
|
||||
@@ -150,26 +157,25 @@ class PhotosController < ApplicationController
|
||||
end
|
||||
|
||||
@object_aspect_ids = []
|
||||
if @parent.aspects
|
||||
@object_aspect_ids = @parent.aspects.map{|a| a.id}
|
||||
if @parent_aspects = @parent.aspects.where(:user_id => current_user.id)
|
||||
@object_aspect_ids = @parent_aspects.map{|a| a.id}
|
||||
end
|
||||
|
||||
comments_hash = Comment.hash_from_post_ids [@parent.id]
|
||||
person_hash = Person.from_post_comment_hash comments_hash
|
||||
@comment_hashes = comments_hash[@parent.id].map do |comment|
|
||||
{:comment => comment,
|
||||
:person => person_hash[comment.person_id]
|
||||
}
|
||||
end
|
||||
@ownership = current_user.owns? @photo
|
||||
|
||||
respond_with @photo
|
||||
else
|
||||
begin
|
||||
redirect_to :back
|
||||
rescue
|
||||
redirect_to aspects_path
|
||||
end
|
||||
end
|
||||
|
||||
respond_with @photo
|
||||
end
|
||||
|
||||
def edit
|
||||
if @photo = current_user.my_posts.where(:_id => params[:id]).first
|
||||
if @photo = current_user.posts.where(:id => params[:id]).first
|
||||
respond_with @photo
|
||||
else
|
||||
redirect_to person_photos_path(current_user.person)
|
||||
@@ -177,7 +183,7 @@ class PhotosController < ApplicationController
|
||||
end
|
||||
|
||||
def update
|
||||
photo = current_user.my_posts.where(:_id => params[:id]).first
|
||||
photo = current_user.posts.where(:id => params[:id]).first
|
||||
if photo
|
||||
if current_user.update_post( photo, params[:photo] )
|
||||
flash.now[:notice] = I18n.t 'photos.update.notice'
|
||||
|
||||
@@ -3,17 +3,36 @@
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class PostsController < ApplicationController
|
||||
skip_before_filter :set_contacts_notifications_and_status
|
||||
skip_before_filter :count_requests
|
||||
skip_before_filter :set_invites
|
||||
skip_before_filter :set_locale
|
||||
skip_before_filter :which_action_and_user
|
||||
skip_before_filter :set_grammatical_gender
|
||||
|
||||
def index
|
||||
if current_user
|
||||
@posts = StatusMessage.joins(:aspects).where(:pending => false
|
||||
).where(Aspect.arel_table[:user_id].eq(current_user.id).or(StatusMessage.arel_table[:public].eq(true))
|
||||
).select('DISTINCT `posts`.*')
|
||||
else
|
||||
@posts = StatusMessage.where(:public => true, :pending => false)
|
||||
end
|
||||
|
||||
params[:tag] ||= 'partytimeexcellent'
|
||||
|
||||
@posts = @posts.tagged_with(params[:tag])
|
||||
@posts = @posts.includes(:comments, :photos).paginate(:page => params[:page], :per_page => 15, :order => 'created_at DESC')
|
||||
|
||||
@fakes = PostsFake.new(@posts)
|
||||
@commenting_disabled = true
|
||||
@pod_url = AppConfig[:pod_uri].host
|
||||
end
|
||||
|
||||
def show
|
||||
@post = Post.first(:id => params[:id], :public => true)
|
||||
@post = Post.where(:id => params[:id], :public => true).includes(:author, :comments => :author).first
|
||||
|
||||
if @post
|
||||
@landing_page = true
|
||||
@person = @post.person
|
||||
@person = @post.author
|
||||
if @person.owner_id
|
||||
I18n.locale = @person.owner.language
|
||||
render "posts/#{@post.class.to_s.underscore}", :layout => true
|
||||
@@ -24,6 +43,6 @@ class PostsController < ApplicationController
|
||||
else
|
||||
flash[:error] = "that post does not exsist!"
|
||||
redirect_to root_url
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
33
app/controllers/profiles_controller.rb
Normal file
33
app/controllers/profiles_controller.rb
Normal file
@@ -0,0 +1,33 @@
|
||||
# Copyright (c) 2010, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class ProfilesController < ApplicationController
|
||||
before_filter :authenticate_user!
|
||||
def edit
|
||||
@person = current_user.person
|
||||
@aspect = :person_edit
|
||||
@profile = @person.profile
|
||||
end
|
||||
|
||||
def update
|
||||
# upload and set new profile photo
|
||||
params[:profile] ||= {}
|
||||
params[:profile][:searchable] ||= false
|
||||
params[:profile][:photo] = Photo.where(:author_id => current_user.person.id,
|
||||
:id => params[:photo_id]).first if params[:photo_id]
|
||||
|
||||
if current_user.update_profile params[:profile]
|
||||
flash[:notice] = I18n.t 'profiles.update.updated'
|
||||
else
|
||||
flash[:error] = I18n.t 'profiles.update.failed'
|
||||
end
|
||||
|
||||
if params[:getting_started]
|
||||
redirect_to getting_started_path(:step => params[:getting_started].to_i+1)
|
||||
else
|
||||
redirect_to edit_profile_path
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -6,16 +6,17 @@ class PublicsController < ApplicationController
|
||||
require File.join(Rails.root, '/lib/diaspora/parser')
|
||||
include Diaspora::Parser
|
||||
|
||||
skip_before_filter :set_contacts_notifications_and_status, :except => [:create, :update]
|
||||
skip_before_filter :set_header_data
|
||||
skip_before_filter :count_requests
|
||||
skip_before_filter :set_invites
|
||||
skip_before_filter :set_locale
|
||||
skip_before_filter :which_action_and_user
|
||||
skip_before_filter :set_grammatical_gender
|
||||
|
||||
layout false
|
||||
caches_page :host_meta
|
||||
|
||||
def hcard
|
||||
@person = Person.find_by_id params[:id]
|
||||
@person = Person.where(:guid => params[:guid]).first
|
||||
unless @person.nil? || @person.owner.nil?
|
||||
render 'publics/hcard'
|
||||
else
|
||||
@@ -29,7 +30,7 @@ class PublicsController < ApplicationController
|
||||
|
||||
def webfinger
|
||||
@person = Person.local_by_account_identifier(params[:q]) if params[:q]
|
||||
unless @person.nil?
|
||||
unless @person.nil?
|
||||
render 'webfinger', :content_type => 'application/xrd+xml'
|
||||
else
|
||||
render :nothing => true, :status => 404
|
||||
@@ -37,9 +38,7 @@ class PublicsController < ApplicationController
|
||||
end
|
||||
|
||||
def hub
|
||||
if params['hub.mode'] == 'subscribe' || params['hub.mode'] == 'unsubscribe'
|
||||
render :text => params['hub.challenge'], :status => 202, :layout => false
|
||||
end
|
||||
render :text => params['hub.challenge'], :status => 202, :layout => false
|
||||
end
|
||||
|
||||
def receive
|
||||
@@ -48,16 +47,16 @@ class PublicsController < ApplicationController
|
||||
return
|
||||
end
|
||||
|
||||
person = Person.first(:id => params[:id])
|
||||
person = Person.where(:guid => params[:guid]).first
|
||||
|
||||
if person.owner_id.nil?
|
||||
Rails.logger.error("Received post for nonexistent person #{params[:id]}")
|
||||
Rails.logger.error("Received post for nonexistent person #{params[:guid]}")
|
||||
render :nothing => true, :status => 404
|
||||
return
|
||||
end
|
||||
|
||||
@user = person.owner
|
||||
Resque.enqueue(Jobs::ReceiveSalmon, @user.id, CGI::unescape(params[:xml]))
|
||||
Resque.enqueue(Job::ReceiveSalmon, @user.id, CGI::unescape(params[:xml]))
|
||||
|
||||
render :nothing => true, :status => 200
|
||||
end
|
||||
|
||||
@@ -13,7 +13,9 @@ class RegistrationsController < Devise::RegistrationsController
|
||||
sign_in_and_redirect(:user, @user)
|
||||
Rails.logger.info("event=registration status=successful user=#{@user.diaspora_handle}")
|
||||
else
|
||||
flash[:error] = @user.errors.full_messages.join(', ')
|
||||
@user.errors.delete(:person)
|
||||
|
||||
flash[:error] = @user.errors.full_messages.join(";")
|
||||
Rails.logger.info("event=registration status=failure errors='#{@user.errors.full_messages.join(', ')}'")
|
||||
render :new
|
||||
end
|
||||
|
||||
@@ -11,7 +11,7 @@ class RequestsController < ApplicationController
|
||||
respond_to :html
|
||||
|
||||
def destroy
|
||||
if notification = Notification.where(:user_id => current_user.id, :target_id=> params[:id]).first
|
||||
if notification = Notification.where(:recipient_id => current_user.id, :target_id=> params[:id]).first
|
||||
notification.update_attributes(:unread=>false)
|
||||
end
|
||||
|
||||
@@ -19,7 +19,7 @@ class RequestsController < ApplicationController
|
||||
if params[:aspect_id]
|
||||
@contact = current_user.accept_and_respond( params[:id], params[:aspect_id])
|
||||
flash[:notice] = I18n.t 'requests.destroy.success'
|
||||
respond_with @contact, :location => current_user.aspect_by_id(params[:aspect_id])
|
||||
respond_with @contact, :location => requests_url
|
||||
else
|
||||
flash[:error] = I18n.t 'requests.destroy.error'
|
||||
respond_with @contact, :location => requests_url
|
||||
@@ -32,10 +32,10 @@ class RequestsController < ApplicationController
|
||||
end
|
||||
|
||||
def create
|
||||
aspect = current_user.aspect_by_id(params[:request][:into])
|
||||
aspect = current_user.aspects.where(:id => params[:request][:into]).first
|
||||
account = params[:request][:to].strip
|
||||
person = Person.by_account_identifier(account)
|
||||
existing_request = Request.from(person).to(current_user.person).first if person
|
||||
existing_request = Request.where(:sender_id => person.id, :recipient_id => current_user.person.id).first if person
|
||||
if existing_request
|
||||
current_user.accept_and_respond(existing_request.id, aspect.id)
|
||||
redirect_to :back
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
# Copyright (c) 2010, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
# licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file.
|
||||
|
||||
class ServicesController < ApplicationController
|
||||
before_filter :authenticate_user!
|
||||
@@ -20,9 +18,8 @@ class ServicesController < ApplicationController
|
||||
user = auth['user_info']
|
||||
|
||||
service = "Services::#{provider.camelize}".constantize.new(:nickname => user['nickname'],
|
||||
:access_token => toke,
|
||||
:access_token => toke,
|
||||
:access_secret => secret,
|
||||
:provider => provider,
|
||||
:uid => auth['uid'])
|
||||
current_user.services << service
|
||||
|
||||
@@ -30,11 +27,10 @@ class ServicesController < ApplicationController
|
||||
if current_user.getting_started
|
||||
redirect_to getting_started_path(:step => 3)
|
||||
else
|
||||
redirect_to services_url
|
||||
redirect_to services_url
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def failure
|
||||
Rails.logger.info "error in oauth #{params.inspect}"
|
||||
flash[:error] = t('services.failure.error')
|
||||
@@ -47,4 +43,35 @@ class ServicesController < ApplicationController
|
||||
flash[:notice] = I18n.t 'services.destroy.success'
|
||||
redirect_to services_url
|
||||
end
|
||||
|
||||
def finder
|
||||
service = current_user.services.where(:type => "Services::#{params[:provider].titleize}").first
|
||||
@friends = service ? service.finder(:remote => params[:remote]) : {}
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
def inviter
|
||||
if current_user.invites == 0
|
||||
flash[:error] = I18n.t 'invitations.create.no_more'
|
||||
redirect_to :back
|
||||
return
|
||||
end
|
||||
|
||||
@uid = params[:uid]
|
||||
|
||||
if i_id = params[:invitation_id]
|
||||
invited_user = Invitation.find(i_id).recipient
|
||||
else
|
||||
invited_user = current_user.invite_user(params[:aspect_id], params[:provider], @uid)
|
||||
end
|
||||
|
||||
@subject = t('services.inviter.join_me_on_diaspora')
|
||||
@message = <<MSG
|
||||
#{t('services.inviter.click_link_to_accept_invitation')}:
|
||||
\n
|
||||
\n
|
||||
#{accept_invitation_url(invited_user, :invitation_token => invited_user.invitation_token)}
|
||||
MSG
|
||||
redirect_to "https://www.facebook.com/?compose=1&id=#{@uid}&subject=#{@subject}&message=#{@message}&sk=messages"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,60 +6,60 @@ class StatusMessagesController < ApplicationController
|
||||
before_filter :authenticate_user!
|
||||
|
||||
respond_to :html
|
||||
respond_to :mobile
|
||||
respond_to :json, :only => :show
|
||||
|
||||
def create
|
||||
params[:status_message][:aspect_ids] = params[:aspect_ids]
|
||||
|
||||
photos = Photo.all(:id.in => [*params[:photos]], :diaspora_handle => current_user.person.diaspora_handle)
|
||||
photos = Photo.where(:id => [*params[:photos]], :diaspora_handle => current_user.person.diaspora_handle)
|
||||
|
||||
public_flag = params[:status_message][:public]
|
||||
public_flag.to_s.match(/(true)/) ? public_flag = true : public_flag = false
|
||||
public_flag.to_s.match(/(true)|(on)/) ? public_flag = true : public_flag = false
|
||||
params[:status_message][:public] = public_flag
|
||||
|
||||
@status_message = current_user.build_post(:status_message, params[:status_message])
|
||||
aspects = current_user.aspects_from_ids(params[:aspect_ids])
|
||||
|
||||
if photos || @status_message.save!(:safe => true)
|
||||
raise 'MongoMapper failed to catch a failed save' unless @status_message.id
|
||||
if !photos.empty?
|
||||
@status_message.photos << photos
|
||||
end
|
||||
if @status_message.save
|
||||
Rails.logger.info("event=create type=status_message chars=#{params[:status_message][:message].length}")
|
||||
|
||||
@status_message.photos += photos unless photos.nil?
|
||||
current_user.add_to_streams(@status_message, aspects)
|
||||
current_user.dispatch_post(@status_message, :url => post_url(@status_message))
|
||||
|
||||
|
||||
for photo in photos
|
||||
photo.public = public_flag
|
||||
photo.save
|
||||
current_user.add_to_streams(photo, aspects)
|
||||
current_user.dispatch_post(photo)
|
||||
receiving_services = params[:services].map{|s| current_user.services.where(
|
||||
:type => "Services::"+s.titleize).first} if params[:services]
|
||||
current_user.dispatch_post(@status_message, :url => post_url(@status_message), :services => receiving_services)
|
||||
if !photos.empty?
|
||||
for photo in photos
|
||||
was_pending = photo.pending
|
||||
if was_pending
|
||||
current_user.add_to_streams(photo, aspects)
|
||||
current_user.dispatch_post(photo)
|
||||
end
|
||||
end
|
||||
photos.update_all(:pending => false, :public => public_flag)
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.js{ render :json => { :post_id => @status_message.id,
|
||||
:html => render_to_string(
|
||||
:partial => 'shared/stream_element',
|
||||
:locals => {
|
||||
:post => @status_message,
|
||||
:person => @status_message.person,
|
||||
:photos => @status_message.photos,
|
||||
:comments => [],
|
||||
:all_aspects => current_user.aspects,
|
||||
:current_user => current_user
|
||||
}
|
||||
)
|
||||
},
|
||||
:status => 201 }
|
||||
format.html{ respond_with @status_message }
|
||||
format.js { render :create, :status => 201}
|
||||
format.html { redirect_to :back}
|
||||
format.mobile{ redirect_to :back}
|
||||
end
|
||||
else
|
||||
if !photos.empty?
|
||||
photos.update_all(:status_message_id => nil)
|
||||
end
|
||||
respond_to do |format|
|
||||
format.js{ render :status => 406 }
|
||||
format.js { render :json =>{:errors => @status_message.errors.full_messages}, :status => 406 }
|
||||
format.html {redirect_to :back}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@status_message = current_user.my_posts.where(:_id => params[:id]).first
|
||||
@status_message = current_user.posts.where(:id => params[:id]).first
|
||||
if @status_message
|
||||
@status_message.destroy
|
||||
render :nothing => true, :status => 200
|
||||
@@ -71,16 +71,19 @@ class StatusMessagesController < ApplicationController
|
||||
|
||||
def show
|
||||
@status_message = current_user.find_visible_post_by_id params[:id]
|
||||
comments_hash = Comment.hash_from_post_ids [@status_message.id]
|
||||
person_hash = Person.from_post_comment_hash comments_hash
|
||||
@comment_hashes = comments_hash[@status_message.id].map do |comment|
|
||||
{:comment => comment,
|
||||
:person => person_hash[comment.person_id]
|
||||
}
|
||||
if @status_message
|
||||
@object_aspect_ids = @status_message.aspects.map{|a| a.id}
|
||||
|
||||
# mark corresponding notification as read
|
||||
if notification = Notification.where(:recipient_id => current_user.id, :target_id => @status_message.id).first
|
||||
notification.unread = false
|
||||
notification.save
|
||||
end
|
||||
|
||||
respond_with @status_message
|
||||
else
|
||||
redirect_to :back
|
||||
end
|
||||
|
||||
@object_aspect_ids = @status_message.aspects.map{|a| a.id}
|
||||
|
||||
respond_with @status_message
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -13,35 +13,54 @@ class UsersController < ApplicationController
|
||||
def edit
|
||||
@aspect = :user_edit
|
||||
@user = current_user
|
||||
@email_prefs = Hash.new(true)
|
||||
@user.user_preferences.each do |pref|
|
||||
@email_prefs[pref.email_type] = false
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
|
||||
u = params[:user]
|
||||
@user = current_user
|
||||
|
||||
params[:user].delete(:password) if params[:user][:password].blank?
|
||||
params[:user].delete(:password_confirmation) if params[:user][:password].blank? and params[:user][:password_confirmation].blank?
|
||||
params[:user].delete(:language) if params[:user][:language].blank?
|
||||
u.delete(:password) if u[:password].blank?
|
||||
u.delete(:password_confirmation) if u[:password].blank? and u[:password_confirmation].blank?
|
||||
u.delete(:language) if u[:language].blank?
|
||||
|
||||
# change email notifications
|
||||
if params[:user][:disable_mail]
|
||||
@user.update_attributes(:disable_mail => params[:user][:disable_mail])
|
||||
if u[:email_preferences]
|
||||
@user.update_user_preferences(u[:email_preferences])
|
||||
flash[:notice] = I18n.t 'users.update.email_notifications_changed'
|
||||
# change passowrd
|
||||
elsif params[:user][:password] && params[:user][:password_confirmation]
|
||||
if @user.update_attributes(:password => params[:user][:password], :password_confirmation => params[:user][:password_confirmation])
|
||||
elsif u[:current_password] && u[:password] && u[:password_confirmation]
|
||||
if @user.update_with_password(u)
|
||||
flash[:notice] = I18n.t 'users.update.password_changed'
|
||||
else
|
||||
flash[:error] = I18n.t 'users.update.password_not_changed'
|
||||
end
|
||||
elsif params[:user][:language]
|
||||
if @user.update_attributes(:language => params[:user][:language])
|
||||
elsif u[:language]
|
||||
if @user.update_attributes(:language => u[:language])
|
||||
I18n.locale = @user.language
|
||||
flash[:notice] = I18n.t 'users.update.language_changed'
|
||||
else
|
||||
flash[:error] = I18n.t 'users.update.language_not_changed'
|
||||
end
|
||||
elsif u[:a_ids]
|
||||
@user.aspects.update_all(:open => false)
|
||||
unless u[:a_ids] == ["home"]
|
||||
@user.aspects.where(:id => u[:a_ids]).update_all(:open => true)
|
||||
end
|
||||
end
|
||||
|
||||
redirect_to edit_user_path(@user)
|
||||
respond_to do |format|
|
||||
format.js{
|
||||
render :nothing => true, :status => 204
|
||||
}
|
||||
format.all{
|
||||
redirect_to edit_user_path(@user)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@@ -55,13 +74,13 @@ class UsersController < ApplicationController
|
||||
user = User.find_by_username(params[:username])
|
||||
|
||||
if user
|
||||
posts = StatusMessage.where(:author_id => user.person.id, :public => true).order('created_at DESC')
|
||||
director = Diaspora::Director.new
|
||||
ostatus_builder = Diaspora::OstatusBuilder.new(user)
|
||||
ostatus_builder = Diaspora::OstatusBuilder.new(user, posts)
|
||||
|
||||
render :xml => director.build(ostatus_builder), :content_type => 'application/atom+xml'
|
||||
else
|
||||
flash[:error] = I18n.t 'users.public.does_not_exist', :username => params[:username]
|
||||
redirect_to root_url
|
||||
redirect_to root_url, :error => I18n.t('users.public.does_not_exist', :username => params[:username])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -71,21 +90,33 @@ class UsersController < ApplicationController
|
||||
@person = @user.person
|
||||
@profile = @user.profile
|
||||
@services = @user.services
|
||||
@requests = Request.to(@person).all
|
||||
service = current_user.services.where(:type => "Services::Facebook").first
|
||||
|
||||
@step = ((params[:step].to_i>0)&&(params[:step].to_i<5)) ? params[:step].to_i : 1
|
||||
@step = ((params[:step].to_i>0)&&(params[:step].to_i<4)) ? params[:step].to_i : 1
|
||||
@step ||= 1
|
||||
|
||||
if @step == 4
|
||||
@user.getting_started = false
|
||||
@user.save
|
||||
if @step == 2 && SERVICES['facebook']['app_id'] == ""
|
||||
@step = 3
|
||||
end
|
||||
|
||||
if @step == 3
|
||||
@requests = Request.where(:recipient_id => @person.id).includes(:sender => :profile).all
|
||||
@friends = service ? service.finder(:local => true) : {}
|
||||
@friends.delete_if{|key, value| @requests.any?{ |r| r.sender_id == value[:person].id} }
|
||||
end
|
||||
|
||||
|
||||
if @step == 3 && @requests.length == 0 && @friends.length == 0
|
||||
@user.update_attributes(:getting_started => false)
|
||||
redirect_to root_path
|
||||
else
|
||||
render "users/getting_started"
|
||||
end
|
||||
render "users/getting_started"
|
||||
end
|
||||
|
||||
def getting_started_completed
|
||||
user = current_user
|
||||
user.update_attributes( :getting_started => false )
|
||||
user.update_attributes(:getting_started => false)
|
||||
redirect_to root_path
|
||||
end
|
||||
|
||||
|
||||
@@ -7,32 +7,27 @@ module ApplicationHelper
|
||||
|
||||
def timeago(time, options = {})
|
||||
options[:class] ||= "timeago"
|
||||
content_tag(:abbr, time.to_s, options.merge(:title => time.getutc.iso8601)) if time
|
||||
end
|
||||
|
||||
def modern_browser?
|
||||
false
|
||||
content_tag(:abbr, time.to_s, options.merge(:title => time.iso8601)) if time
|
||||
end
|
||||
|
||||
def page_title text=nil
|
||||
title = ""
|
||||
if text.blank?
|
||||
title = "#{current_user.name} | " if current_user
|
||||
title = "#{current_user.name}" if current_user
|
||||
else
|
||||
title = "#{text} | "
|
||||
title = "#{text}"
|
||||
end
|
||||
title += "DIASPORA*"
|
||||
end
|
||||
|
||||
def aspects_with_post aspects, post
|
||||
aspects.select do |a|
|
||||
post.aspect_ids.include?(a.id)
|
||||
aspects.select do |aspect|
|
||||
PostVisibility.exists?(:aspect_id => aspect.id, :post_id => post.id)
|
||||
end
|
||||
end
|
||||
|
||||
def aspects_without_post aspects, post
|
||||
aspects.reject do |a|
|
||||
post.aspect_ids.include?(a.id)
|
||||
aspects.reject do |aspect|
|
||||
PostVisibility.exists?(:aspect_id => aspect.id, :post_id => post.id)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -68,7 +63,7 @@ module ApplicationHelper
|
||||
param_string << "#{k}=#{v}"
|
||||
end
|
||||
end
|
||||
"<li>
|
||||
"<li>
|
||||
<a href='/aspects/#{aspect.id}#{param_string}'>
|
||||
#{aspect.name}
|
||||
</a>
|
||||
@@ -100,7 +95,7 @@ module ApplicationHelper
|
||||
def mine?(post)
|
||||
current_user.owns? post
|
||||
end
|
||||
|
||||
|
||||
def type_partial(post)
|
||||
class_name = post.class.name.to_s.underscore
|
||||
"#{class_name.pluralize}/#{class_name}"
|
||||
@@ -108,7 +103,6 @@ module ApplicationHelper
|
||||
|
||||
def how_long_ago(obj)
|
||||
timeago(obj.created_at)
|
||||
#I18n.t('ago', :time => time_ago_in_words(obj.created_at, true))
|
||||
end
|
||||
|
||||
def person_url(person)
|
||||
@@ -135,28 +129,21 @@ module ApplicationHelper
|
||||
end
|
||||
|
||||
def person_image_tag(person, size=:thumb_small)
|
||||
"<img alt=\"#{h(person.name)}\" class=\"avatar\" data-person_id=\"#{person.id}\" src=\"#{image_or_default(person, size)}\" title=\"#{h(person.name)}\">".html_safe
|
||||
"<img alt=\"#{h(person.name)}\" class=\"avatar\" data-person_id=\"#{person.id}\" src=\"#{person.profile.image_url(size)}\" title=\"#{h(person.name)}\">".html_safe
|
||||
end
|
||||
|
||||
def person_link(person)
|
||||
"<a href='/people/#{person.id}'>
|
||||
def person_link(person, opts={})
|
||||
"<a href='/people/#{person.id}' class='#{opts[:class]}'>
|
||||
#{h(person.name)}
|
||||
</a>".html_safe
|
||||
end
|
||||
|
||||
def image_or_default(person, size=:thumb_large)
|
||||
image_location = person.profile.image_url(size) if person.profile
|
||||
image_location ||= person.profile.image_url(:thumb_large) if person.profile #backwards compatability for old profile pictures
|
||||
image_location ||= "/images/user/default.png"
|
||||
image_location
|
||||
end
|
||||
|
||||
def hard_link(string, path)
|
||||
link_to string, path, :rel => 'external'
|
||||
end
|
||||
|
||||
def person_image_link(person, opts = {})
|
||||
return "" if person.nil?
|
||||
return "" if person.nil? || person.profile.nil?
|
||||
if opts[:to] == :photos
|
||||
link_to person_image_tag(person, opts[:size]), person_photos_path(person)
|
||||
else
|
||||
@@ -178,11 +165,12 @@ module ApplicationHelper
|
||||
end
|
||||
|
||||
message = process_links(message)
|
||||
message = process_youtube(message)
|
||||
message = process_vimeo(message, options[:vimeo_maps])
|
||||
message = process_autolinks(message)
|
||||
message = process_emphasis(message)
|
||||
message = process_youtube_again(message, options[:youtube_maps])
|
||||
message = process_youtube(message, options[:youtube_maps])
|
||||
message = process_vimeo(message, options[:vimeo_maps])
|
||||
|
||||
message.gsub!(/<3/, "♥")
|
||||
|
||||
if options[:newlines]
|
||||
message.gsub!(/\n+/, '<br />')
|
||||
@@ -191,6 +179,7 @@ module ApplicationHelper
|
||||
return message
|
||||
end
|
||||
|
||||
|
||||
def process_links(message)
|
||||
message.gsub!(/\[([^\[]+)\]\(([^ ]+) \"(([^&]|(&[^q])|(&q[^u])|(&qu[^o])|(&quo[^t])|("[^;]))+)\"\)/) do |m|
|
||||
escape = "\\"
|
||||
@@ -217,22 +206,31 @@ module ApplicationHelper
|
||||
return message
|
||||
end
|
||||
|
||||
def process_youtube(message)
|
||||
message.gsub!(/( |^)(http:\/\/)?www\.youtube\.com\/watch[^ ]*v=([A-Za-z0-9_]+)(&[^ ]*|)/) do |m|
|
||||
res = "#{$1}youtube.com::#{$3}"
|
||||
res.gsub!(/(\*|_)/) { |m| "\\#{$1}" }
|
||||
res
|
||||
def process_youtube(message, youtube_maps)
|
||||
regex = /( |^)(http:\/\/)?www\.youtube\.com\/watch[^ ]*v=([A-Za-z0-9_\-]+)(&[^ ]*|)/
|
||||
processed_message = message.gsub(regex) do |matched_string|
|
||||
match_data = matched_string.match(regex)
|
||||
video_id = match_data[3]
|
||||
if youtube_maps && youtube_maps[video_id]
|
||||
title = h(CGI::unescape(youtube_maps[video_id]))
|
||||
else
|
||||
title = I18n.t 'application.helper.video_title.unknown'
|
||||
end
|
||||
' <a class="video-link" data-host="youtube.com" data-video-id="' + video_id + '" href="'+ match_data[0].strip + '" target="_blank">Youtube: ' + title + '</a>'
|
||||
end
|
||||
return message
|
||||
return processed_message
|
||||
end
|
||||
|
||||
def process_autolinks(message)
|
||||
message.gsub!(/( |^)(www\.[^\s]+\.[^\s])/, '\1http://\2')
|
||||
message.gsub!(/(<a target="\\?_blank" href=")?(https|http|ftp):\/\/([^\s]+)/) do |m|
|
||||
if !$1.nil?
|
||||
captures = [$1,$2,$3]
|
||||
if !captures[0].nil?
|
||||
m
|
||||
elsif m.match(/(youtube|vimeo)/)
|
||||
m.gsub(/(\*|_)/) { |m| "\\#{$1}" } #remove markers on markdown chars to not markdown inside links
|
||||
else
|
||||
res = %{<a target="_blank" href="#{$2}://#{$3}">#{$3}</a>}
|
||||
res = %{<a target="_blank" href="#{captures[1]}://#{captures[2]}">#{captures[2]}</a>}
|
||||
res.gsub!(/(\*|_)/) { |m| "\\#{$1}" }
|
||||
res
|
||||
end
|
||||
@@ -255,35 +253,33 @@ module ApplicationHelper
|
||||
return message
|
||||
end
|
||||
|
||||
def process_youtube_again(message, youtube_maps)
|
||||
while youtube = message.match(/youtube\.com::([A-Za-z0-9_\\\-]+)/)
|
||||
video_id = youtube[1]
|
||||
if youtube_maps && youtube_maps[video_id]
|
||||
title = youtube_maps[video_id]
|
||||
else
|
||||
title = I18n.t 'application.helper.video_title.unknown'
|
||||
end
|
||||
message.gsub!('youtube.com::'+video_id, '<a class="video-link" data-host="youtube.com" data-video-id="' + video_id + '" href="#video">Youtube: ' + title + '</a>')
|
||||
end
|
||||
return message
|
||||
end
|
||||
|
||||
|
||||
def process_vimeo(message, vimeo_maps)
|
||||
regex = /https?:\/\/(?:w{3}\.)?vimeo.com\/(\d{6,})/
|
||||
while vimeo = message.match(regex)
|
||||
video_id = vimeo[1]
|
||||
processed_message = message.gsub(regex) do |matched_string|
|
||||
match_data = message.match(regex)
|
||||
video_id = match_data[1]
|
||||
if vimeo_maps && vimeo_maps[video_id]
|
||||
title = vimeo_maps[video_id]
|
||||
title = h(CGI::unescape(vimeo_maps[video_id]))
|
||||
else
|
||||
title = I18n.t 'application.helper.video_title.unknown'
|
||||
end
|
||||
message.gsub!(vimeo[0], '<a class="video-link" data-host="vimeo.com" data-video-id="' + video_id + '" href="#video">Vimeo: ' + title + '</a>')
|
||||
' <a class="video-link" data-host="vimeo.com" data-video-id="' + video_id + '" href="' + match_data[0] + '" target="_blank">Vimeo: ' + title + '</a>'
|
||||
end
|
||||
return message
|
||||
return processed_message
|
||||
end
|
||||
|
||||
def info_text(text)
|
||||
image_tag 'icons/monotone_question.png', :class => 'what_is_this', :title => text
|
||||
end
|
||||
|
||||
def get_javascript_strings_for(language)
|
||||
defaults = I18n.t('javascripts', :locale => DEFAULT_LANGUAGE)
|
||||
|
||||
if language != DEFAULT_LANGUAGE
|
||||
translations = I18n.t('javascripts', :locale => language)
|
||||
defaults.update(translations)
|
||||
end
|
||||
|
||||
defaults
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
# Copyright (c) 2010, Diaspora Inc. This file is
|
||||
#/ Copyright (c) 2010, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
module AspectsHelper
|
||||
def link_for_aspect(aspect, opts={})
|
||||
opts[:params] ||= {}
|
||||
opts[:params] = opts[:params].merge("a_ids[]" => aspect.id)
|
||||
params ||= {}
|
||||
opts[:params] = opts[:params].merge("a_ids[]" => aspect.id, :created_at => params[:created_at])
|
||||
|
||||
link_to aspect.name, aspects_path( opts[:params] ), opts
|
||||
end
|
||||
@@ -18,47 +19,38 @@ module AspectsHelper
|
||||
end
|
||||
end
|
||||
|
||||
def add_to_aspect_button(aspect_id, person_id)
|
||||
def add_to_aspect_button(aspect_id, person_id, kontroller)
|
||||
link_to image_tag('icons/monotone_plus_add_round.png'),
|
||||
{:controller => "aspects",
|
||||
:action => 'add_to_aspect',
|
||||
{:controller => kontroller,
|
||||
:action => 'create',
|
||||
:aspect_id => aspect_id,
|
||||
:person_id => person_id},
|
||||
:remote => true,
|
||||
:method => 'post',
|
||||
:class => 'add button'
|
||||
end
|
||||
|
||||
def remove_from_aspect_button(aspect_id, person_id)
|
||||
link_to image_tag('icons/monotone_check_yes.png'),
|
||||
{:controller => "aspects",
|
||||
:action => 'remove_from_aspect',
|
||||
{:controller => "aspect_memberships",
|
||||
:action => 'destroy',
|
||||
:id => 42,
|
||||
:aspect_id => aspect_id,
|
||||
:person_id => person_id},
|
||||
:remote => true,
|
||||
:method => 'delete',
|
||||
:class => 'added button'
|
||||
end
|
||||
|
||||
def aspect_membership_button(aspect_id, contact, person)
|
||||
if contact.nil? || !contact.aspect_ids.include?(aspect_id)
|
||||
add_to_aspect_button(aspect_id, person.id)
|
||||
else
|
||||
remove_from_aspect_button(aspect_id, person.id)
|
||||
end
|
||||
def contact_or_membership(contact)
|
||||
(contact.persisted?) ? 'aspect_memberships' : 'contacts'
|
||||
end
|
||||
|
||||
def publisher_description(aspect_count, aspect=nil)
|
||||
if aspect && aspect == :all
|
||||
str = t('.share_with_all')
|
||||
def aspect_membership_button(aspect, contact, person)
|
||||
if contact.nil? || !aspect.contacts.include?(contact)
|
||||
add_to_aspect_button(aspect.id, person.id, contact_or_membership(contact))
|
||||
else
|
||||
str = "#{t('.post_a_message_to', :aspect => aspect_count)} "
|
||||
if aspect_count == 1
|
||||
str += t('_aspect').downcase
|
||||
else
|
||||
str += t('_aspects').downcase
|
||||
end
|
||||
remove_from_aspect_button(aspect.id, person.id)
|
||||
end
|
||||
(link_to str, '#', :id => 'expand_publisher').html_safe
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
5
app/helpers/conversations_helper.rb
Normal file
5
app/helpers/conversations_helper.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
module ConversationsHelper
|
||||
def new_message_text(count)
|
||||
t('conversations.helper.new_messages', :count => count)
|
||||
end
|
||||
end
|
||||
@@ -1,36 +1,40 @@
|
||||
module NotificationsHelper
|
||||
def object_link(note)
|
||||
kind = note.kind
|
||||
translation = t("notifications.#{kind}")
|
||||
case kind
|
||||
when 'request_accepted'
|
||||
translation
|
||||
when 'new_request'
|
||||
translation
|
||||
when 'comment_on_post'
|
||||
comment = Comment.first(:id => note.target_id)
|
||||
if comment
|
||||
"#{translation} #{link_to t('notifications.post'), object_path(comment.post)}".html_safe
|
||||
target_type = note.translation_key
|
||||
if note.instance_of?(Notifications::Mentioned)
|
||||
post = Mention.find(note.target_id).post
|
||||
if post
|
||||
"#{translation(target_type)} #{link_to t('notifications.post'), object_path(post)}".html_safe
|
||||
else
|
||||
"#{translation} #{t('notifications.deleted')} #{t('notifications.post')}"
|
||||
"#{translation(target_type)} #{t('notifications.deleted')} #{t('notifications.post')}"
|
||||
end
|
||||
when 'also_commented'
|
||||
comment = Comment.first(:id => note.target_id)
|
||||
if comment
|
||||
"#{translation} #{link_to t('notifications.post'), object_path(comment.post)}".html_safe
|
||||
elsif note.instance_of?(Notifications::RequestAccepted)
|
||||
translation(target_type)
|
||||
elsif note.instance_of?(Notifications::NewRequest)
|
||||
translation(target_type)
|
||||
elsif note.instance_of?(Notifications::CommentOnPost)
|
||||
post = Post.where(:id => note.target_id).first
|
||||
if post
|
||||
"#{translation(target_type)} #{link_to t('notifications.post'), object_path(post)}".html_safe
|
||||
else
|
||||
"#{translation} #{t('notifications.deleted')} #{t('notifications.post')}"
|
||||
"#{translation(target_type)} #{t('notifications.deleted')} #{t('notifications.post')}"
|
||||
end
|
||||
elsif note.instance_of?(Notifications::AlsoCommented)
|
||||
post = Post.where(:id => note.target_id).first
|
||||
if post
|
||||
"#{translation(target_type, post.author.name)} #{link_to t('notifications.post'), object_path(post)}".html_safe
|
||||
else
|
||||
t('notifications.also_commented_deleted')
|
||||
end
|
||||
else
|
||||
end
|
||||
end
|
||||
|
||||
def translation(target_type, post_author = nil)
|
||||
t("notifications.#{target_type}", :post_author => post_author)
|
||||
end
|
||||
|
||||
def new_notification_text(count)
|
||||
if count > 0
|
||||
t('new_notifications', :count => count)
|
||||
else
|
||||
t('no_new_notifications')
|
||||
end
|
||||
t('notifications.helper.new_notifications', :count => count)
|
||||
end
|
||||
|
||||
def new_notification_link(count)
|
||||
@@ -38,4 +42,12 @@ module NotificationsHelper
|
||||
link_to new_notification_text(count), notifications_path
|
||||
end
|
||||
end
|
||||
|
||||
def notification_people_link(note)
|
||||
note.actors.collect{ |person| link_to("#{h(person.name.titlecase)}", person_path(person))}.join(", ").html_safe
|
||||
end
|
||||
|
||||
def peoples_names(note)
|
||||
note.actors.map{|p| p.name}.join(",")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -22,9 +22,9 @@ module PeopleHelper
|
||||
|
||||
def birthday_format(bday)
|
||||
if bday.year == 1000
|
||||
bday.strftime("%B %d")
|
||||
I18n.l bday, :format => I18n.t('date.formats.birthday')
|
||||
else
|
||||
bday.strftime("%B %d %Y")
|
||||
I18n.l bday, :format => I18n.t('date.formats.birthday_with_year')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
2
app/helpers/private_messages_helper.rb
Normal file
2
app/helpers/private_messages_helper.rb
Normal file
@@ -0,0 +1,2 @@
|
||||
module PrivateMessagesHelper
|
||||
end
|
||||
@@ -10,7 +10,7 @@ module RequestsHelper
|
||||
|
||||
def new_request_link(request_count)
|
||||
if request_count > 0
|
||||
link_to t('new_requests', :count => @request_count), aspects_manage_path
|
||||
link_to t('requests.helper.new_requests', :count => @request_count), aspects_manage_path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,7 +7,13 @@ module SocketsHelper
|
||||
include NotificationsHelper
|
||||
|
||||
def obj_id(object)
|
||||
object.respond_to?(:post_id) ? object.post_id : object.id
|
||||
if object.respond_to?(:post_id)
|
||||
object.post_id
|
||||
elsif object.respond_to?(:post_guid)
|
||||
object.post_guid
|
||||
else
|
||||
object.id
|
||||
end
|
||||
end
|
||||
|
||||
def action_hash(user, object, opts={})
|
||||
@@ -20,11 +26,11 @@ module SocketsHelper
|
||||
|
||||
if object.is_a? StatusMessage
|
||||
post_hash = {:post => object,
|
||||
:person => object.person,
|
||||
:author => object.author,
|
||||
:photos => object.photos,
|
||||
:comments => object.comments.map{|c|
|
||||
{:comment => c,
|
||||
:person => c.person
|
||||
:author => c.author
|
||||
}
|
||||
},
|
||||
:current_user => user,
|
||||
@@ -37,22 +43,22 @@ module SocketsHelper
|
||||
:person => object,
|
||||
:all_aspects => user.aspects,
|
||||
:contact => user.contact_for(object),
|
||||
:request => user.request_for(object),
|
||||
:request => user.request_from(object),
|
||||
:current_user => user}
|
||||
v = render_to_string(:partial => 'people/person', :locals => person_hash)
|
||||
|
||||
elsif object.is_a? Comment
|
||||
v = render_to_string(:partial => 'comments/comment', :locals => {:hash => {:comment => object, :person => object.person}})
|
||||
v = render_to_string(:partial => 'comments/comment', :locals => {:comment => object, :person => object.author})
|
||||
|
||||
elsif object.is_a? Notification
|
||||
v = render_to_string(:partial => 'notifications/popup', :locals => {:note => object, :person => object.person})
|
||||
v = render_to_string(:partial => 'notifications/popup', :locals => {:note => object, :person => opts[:actor]})
|
||||
|
||||
else
|
||||
v = render_to_string(:partial => type_partial(object), :locals => {:post => object, :current_user => user}) unless object.is_a? Retraction
|
||||
raise "#{object.inspect} with class #{object.class} is not actionhashable." unless object.is_a? Retraction
|
||||
end
|
||||
rescue Exception => e
|
||||
Rails.logger.error("event=socket_render status=fail user=#{user.diaspora_handle} object=#{object.id.to_s}")
|
||||
raise e.original_exception
|
||||
raise e
|
||||
end
|
||||
action_hash = {:class =>object.class.to_s.underscore.pluralize, :html => v, :post_id => obj_id(object)}
|
||||
action_hash.merge! opts
|
||||
@@ -63,12 +69,12 @@ module SocketsHelper
|
||||
if object.is_a? Comment
|
||||
post = object.post
|
||||
action_hash[:comment_id] = object.id
|
||||
action_hash[:my_post?] = (post.person.owner.id == uid)
|
||||
action_hash[:post_guid] = post.id
|
||||
action_hash[:my_post?] = (post.author.owner_id == uid)
|
||||
action_hash[:post_guid] = post.guid
|
||||
|
||||
end
|
||||
|
||||
action_hash[:mine?] = object.person && (object.person.owner.id == uid) if object.respond_to?(:person)
|
||||
action_hash[:mine?] = object.author && (object.author.owner_id == uid) if object.respond_to?(:author)
|
||||
|
||||
I18n.locale = old_locale unless user.nil?
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@ module StreamHelper
|
||||
end
|
||||
end
|
||||
|
||||
def new_comment_form(post_id)
|
||||
def new_comment_form(post_id, current_user)
|
||||
@form ||= controller.render_to_string(
|
||||
:partial => 'comments/new_comment', :locals => {:post_id => GSUB_THIS})
|
||||
:partial => 'comments/new_comment', :locals => {:post_id => GSUB_THIS, :current_user => current_user})
|
||||
@form.gsub(GSUB_THIS, post_id.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,7 +3,7 @@ class Notifier < ActionMailer::Base
|
||||
|
||||
default :from => AppConfig[:smtp_sender_address]
|
||||
|
||||
ATTACHMENT = File.read("#{Rails.root}/public/images/white_on_grey.png")
|
||||
ATTACHMENT = File.read("#{Rails.root}/public/images/logo_caps.png")
|
||||
|
||||
def self.admin(string, recipients, opts = {})
|
||||
mails = []
|
||||
@@ -17,7 +17,7 @@ class Notifier < ActionMailer::Base
|
||||
def single_admin(string, recipient)
|
||||
@recipient = recipient
|
||||
@string = string.html_safe
|
||||
attachments.inline['diaspora_white_on_grey.png'] = ATTACHMENT
|
||||
attachments.inline['logo_caps.png'] = ATTACHMENT
|
||||
mail(:to => @recipient.email,
|
||||
:subject => I18n.t('notifier.single_admin.subject'), :host => AppConfig[:pod_uri].host)
|
||||
end
|
||||
@@ -28,10 +28,12 @@ class Notifier < ActionMailer::Base
|
||||
|
||||
log_mail(recipient_id, sender_id, 'new_request')
|
||||
|
||||
attachments.inline['diaspora_white_on_grey.png'] = ATTACHMENT
|
||||
attachments.inline['logo_caps.png'] = ATTACHMENT
|
||||
|
||||
mail(:to => "\"#{@receiver.name}\" <#{@receiver.email}>",
|
||||
:subject => I18n.t('notifier.new_request.subject', :from => @sender.name), :host => AppConfig[:pod_uri].host)
|
||||
I18n.with_locale(@receiver.language) do
|
||||
mail(:to => "\"#{@receiver.name}\" <#{@receiver.email}>",
|
||||
:subject => I18n.t('notifier.new_request.subject', :from => @sender.name), :host => AppConfig[:pod_uri].host)
|
||||
end
|
||||
end
|
||||
|
||||
def request_accepted(recipient_id, sender_id)
|
||||
@@ -40,43 +42,82 @@ class Notifier < ActionMailer::Base
|
||||
|
||||
log_mail(recipient_id, sender_id, 'request_accepted')
|
||||
|
||||
attachments.inline['diaspora_white_on_grey.png'] = ATTACHMENT
|
||||
attachments.inline['logo_caps.png'] = ATTACHMENT
|
||||
|
||||
mail(:to => "\"#{@receiver.name}\" <#{@receiver.email}>",
|
||||
:subject => I18n.t('notifier.request_accepted.subject', :name => @sender.name), :host => AppConfig[:pod_uri].host)
|
||||
I18n.with_locale(@receiver.language) do
|
||||
mail(:to => "\"#{@receiver.name}\" <#{@receiver.email}>",
|
||||
:subject => I18n.t('notifier.request_accepted.subject', :name => @sender.name), :host => AppConfig[:pod_uri].host)
|
||||
end
|
||||
end
|
||||
|
||||
def mentioned(recipient_id, sender_id, target_id)
|
||||
@receiver = User.find_by_id(recipient_id)
|
||||
@sender = Person.find_by_id(sender_id)
|
||||
@post = Mention.find_by_id(target_id).post
|
||||
|
||||
log_mail(recipient_id, sender_id, 'mentioned')
|
||||
|
||||
attachments.inline['logo_caps.png'] = ATTACHMENT
|
||||
|
||||
I18n.with_locale(@receiver.language) do
|
||||
mail(:to => "\"#{@receiver.name}\" <#{@receiver.email}>",
|
||||
:subject => I18n.t('notifier.mentioned.subject', :name => @sender.name), :host => AppConfig[:pod_uri].host)
|
||||
end
|
||||
end
|
||||
|
||||
def comment_on_post(recipient_id, sender_id, comment_id)
|
||||
@receiver = User.find_by_id(recipient_id)
|
||||
@sender = Person.find_by_id(sender_id)
|
||||
@comment = Comment.find_by_id(comment_id)
|
||||
@comment = Comment.find_by_id(comment_id)
|
||||
|
||||
log_mail(recipient_id, sender_id, 'comment_on_post')
|
||||
|
||||
attachments.inline['diaspora_white_on_grey.png'] = ATTACHMENT
|
||||
attachments.inline['logo_caps.png'] = ATTACHMENT
|
||||
|
||||
mail(:to => "\"#{@receiver.name}\" <#{@receiver.email}>",
|
||||
:subject => I18n.t('notifier.comment_on_post.subject', :name => @sender.name), :host => AppConfig[:pod_uri].host)
|
||||
I18n.with_locale(@receiver.language) do
|
||||
mail(:to => "\"#{@receiver.name}\" <#{@receiver.email}>",
|
||||
:subject => I18n.t('notifier.comment_on_post.subject', :name => @sender.name), :host => AppConfig[:pod_uri].host)
|
||||
end
|
||||
end
|
||||
|
||||
def also_commented(recipient_id, sender_id, comment_id)
|
||||
@receiver = User.find_by_id(recipient_id)
|
||||
@sender = Person.find_by_id(sender_id)
|
||||
@comment = Comment.find_by_id(comment_id)
|
||||
@post_author_name = @comment.post.person.name
|
||||
|
||||
@comment = Comment.find_by_id(comment_id)
|
||||
@post_author_name = @comment.post.author.name
|
||||
|
||||
|
||||
log_mail(recipient_id, sender_id, 'comment_on_post')
|
||||
|
||||
attachments.inline['diaspora_white_on_grey.png'] = ATTACHMENT
|
||||
attachments.inline['logo_caps.png'] = ATTACHMENT
|
||||
|
||||
mail(:to => "\"#{@receiver.name}\" <#{@receiver.email}>",
|
||||
:subject => I18n.t('notifier.also_commented.subject', :name => @sender.name, :post_author => @post_author_name ), :host => AppConfig[:pod_uri].host)
|
||||
I18n.with_locale(@receiver.language) do
|
||||
mail(:to => "\"#{@receiver.name}\" <#{@receiver.email}>",
|
||||
:subject => I18n.t('notifier.also_commented.subject', :name => @sender.name, :post_author => @post_author_name ), :host => AppConfig[:pod_uri].host)
|
||||
end
|
||||
end
|
||||
|
||||
def private_message(recipient_id, sender_id, message_id)
|
||||
@receiver = User.find_by_id(recipient_id)
|
||||
@sender = Person.find_by_id(sender_id)
|
||||
@message = Message.find_by_id(message_id)
|
||||
@conversation = @message.conversation
|
||||
@participants = @conversation.participants
|
||||
|
||||
|
||||
log_mail(recipient_id, sender_id, 'private_message')
|
||||
|
||||
attachments.inline['logo_caps.png'] = ATTACHMENT
|
||||
|
||||
I18n.with_locale(@receiver.language) do
|
||||
mail(:to => "\"#{@receiver.name}\" <#{@receiver.email}>",
|
||||
:subject => I18n.t('notifier.private_message.subject', :name => @sender.name), :host => AppConfig[:pod_uri].host)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def log_mail recipient_id, sender_id, type
|
||||
log_string = "event=mail mail_type=#{type} db_name=#{MongoMapper.database.name} recipient_id=#{recipient_id} sender_id=#{sender_id}"
|
||||
log_string = "event=mail mail_type=#{type} recipient_id=#{recipient_id} sender_id=#{sender_id}"
|
||||
if @receiver && @sender
|
||||
log_string << "models_found=true sender_handle=#{@sender.diaspora_handle} recipient_handle=#{@receiver.diaspora_handle}"
|
||||
else
|
||||
|
||||
@@ -2,46 +2,27 @@
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class Aspect
|
||||
include MongoMapper::Document
|
||||
class Aspect < ActiveRecord::Base
|
||||
belongs_to :user
|
||||
|
||||
key :name, String
|
||||
key :post_ids, Array
|
||||
has_many :aspect_memberships
|
||||
has_many :contacts, :through => :aspect_memberships
|
||||
|
||||
many :contacts, :foreign_key => 'aspect_ids', :class_name => 'Contact'
|
||||
many :posts, :in => :post_ids, :class_name => 'Post'
|
||||
|
||||
belongs_to :user, :class_name => 'User'
|
||||
has_many :post_visibilities
|
||||
has_many :posts, :through => :post_visibilities
|
||||
|
||||
validates_presence_of :name
|
||||
validates_length_of :name, :maximum => 20
|
||||
validates_uniqueness_of :name, :scope => :user_id
|
||||
validates_uniqueness_of :name, :scope => :user_id, :case_sensitive => false
|
||||
|
||||
attr_accessible :name
|
||||
|
||||
|
||||
before_validation do
|
||||
name.strip!
|
||||
end
|
||||
|
||||
timestamps!
|
||||
|
||||
def to_s
|
||||
name
|
||||
end
|
||||
|
||||
def person_objects
|
||||
person_ids = people.map{|x| x.person_id}
|
||||
Person.all(:id.in => person_ids)
|
||||
end
|
||||
|
||||
def as_json(opts = {})
|
||||
{
|
||||
:aspect => {
|
||||
:name => self.name,
|
||||
:people => self.people.each{|person| person.as_json},
|
||||
:posts => self.posts.each {|post| post.as_json },
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
23
app/models/aspect_membership.rb
Normal file
23
app/models/aspect_membership.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
# Copyright (c) 2010, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class AspectMembership < ActiveRecord::Base
|
||||
|
||||
belongs_to :aspect
|
||||
belongs_to :contact
|
||||
has_one :user, :through => :contact
|
||||
has_one :person, :through => :contact
|
||||
|
||||
before_destroy :ensure_membership
|
||||
|
||||
|
||||
def ensure_membership
|
||||
if self.contact.aspect_memberships.count == 1
|
||||
errors[:base] << I18n.t('shared.contact_list.cannot_remove')
|
||||
false
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -2,139 +2,58 @@
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class HandleValidator < ActiveModel::Validator
|
||||
def validate(document)
|
||||
unless document.diaspora_handle == document.person.diaspora_handle
|
||||
document.errors[:base] << "Diaspora handle and person handle must match"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Comment
|
||||
class Comment < ActiveRecord::Base
|
||||
require File.join(Rails.root, 'lib/diaspora/web_socket')
|
||||
require File.join(Rails.root, 'lib/youtube_titles')
|
||||
include YoutubeTitles
|
||||
include MongoMapper::Document
|
||||
include ROXML
|
||||
|
||||
include Diaspora::Webhooks
|
||||
include Encryptable
|
||||
include Diaspora::Relayable
|
||||
include Diaspora::Guid
|
||||
|
||||
include Diaspora::Socketable
|
||||
|
||||
xml_reader :text
|
||||
xml_reader :diaspora_handle
|
||||
xml_reader :post_id
|
||||
xml_reader :_id
|
||||
xml_attr :text
|
||||
xml_attr :diaspora_handle
|
||||
|
||||
key :text, String
|
||||
key :post_id, ObjectId
|
||||
key :person_id, ObjectId
|
||||
key :diaspora_handle, String
|
||||
belongs_to :post, :touch => true
|
||||
belongs_to :author, :class_name => 'Person'
|
||||
|
||||
belongs_to :post, :class_name => "Post"
|
||||
belongs_to :person, :class_name => "Person"
|
||||
|
||||
validates_presence_of :text, :diaspora_handle, :post
|
||||
validates_length_of :text, :maximum => 500
|
||||
validates_with HandleValidator
|
||||
validates_presence_of :text, :post
|
||||
validates_length_of :text, :maximum => 2500
|
||||
|
||||
serialize :youtube_titles, Hash
|
||||
before_save do
|
||||
get_youtube_title text
|
||||
self.text.strip! unless self.text.nil?
|
||||
end
|
||||
def diaspora_handle
|
||||
self.author.diaspora_handle
|
||||
end
|
||||
def diaspora_handle= nh
|
||||
self.author = Webfinger.new(nh).fetch
|
||||
end
|
||||
|
||||
timestamps!
|
||||
|
||||
def notification_type(user, person)
|
||||
if self.post.diaspora_handle == user.diaspora_handle
|
||||
return "comment_on_post"
|
||||
elsif self.post.comments.all(:diaspora_handle => user.diaspora_handle) != [] && self.diaspora_handle != user.diaspora_handle
|
||||
return "also_commented"
|
||||
if self.post.author == user.person
|
||||
return Notifications::CommentOnPost
|
||||
elsif self.post.comments.where(:author_id => user.person.id) != [] && self.author_id != user.person.id
|
||||
return Notifications::AlsoCommented
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def subscribers(user)
|
||||
if user.owns?(self.post)
|
||||
p = self.post.subscribers(user)
|
||||
elsif user.owns?(self)
|
||||
p = [self.post.person]
|
||||
end
|
||||
p
|
||||
def parent_class
|
||||
Post
|
||||
end
|
||||
|
||||
def receive(user, person)
|
||||
commenter = self.person
|
||||
unless self.post.person == user.person || self.verify_post_creator_signature
|
||||
Rails.logger.info("event=receive status=abort reason='comment signature not valid' recipient=#{user.diaspora_handle} sender=#{self.post.person.diaspora_handle} payload_type=#{self.class} post_id=#{self.post_id}")
|
||||
return
|
||||
end
|
||||
|
||||
user.visible_people = user.visible_people | [commenter]
|
||||
user.save
|
||||
|
||||
commenter.save
|
||||
|
||||
#sign comment as the post creator if you've been hit UPSTREAM
|
||||
if user.owns? self.post
|
||||
self.post_creator_signature = self.sign_with_key(user.encryption_key)
|
||||
self.save
|
||||
end
|
||||
|
||||
#dispatch comment DOWNSTREAM, received it via UPSTREAM
|
||||
unless user.owns?(self)
|
||||
self.save
|
||||
user.dispatch_comment(self)
|
||||
end
|
||||
|
||||
self.socket_to_uid(user, :aspect_ids => self.post.aspect_ids)
|
||||
self
|
||||
def parent
|
||||
self.post
|
||||
end
|
||||
|
||||
#ENCRYPTION
|
||||
|
||||
xml_reader :creator_signature
|
||||
xml_reader :post_creator_signature
|
||||
|
||||
key :creator_signature, String
|
||||
key :post_creator_signature, String
|
||||
|
||||
def signable_accessors
|
||||
accessors = self.class.roxml_attrs.collect{|definition|
|
||||
definition.accessor}
|
||||
accessors.delete 'person'
|
||||
accessors.delete 'creator_signature'
|
||||
accessors.delete 'post_creator_signature'
|
||||
accessors
|
||||
def parent= parent
|
||||
self.post = parent
|
||||
end
|
||||
|
||||
def signable_string
|
||||
signable_accessors.collect{|accessor|
|
||||
(self.send accessor.to_sym).to_s}.join ';'
|
||||
end
|
||||
|
||||
def verify_post_creator_signature
|
||||
verify_signature(post_creator_signature, post.person)
|
||||
end
|
||||
|
||||
def signature_valid?
|
||||
verify_signature(creator_signature, person)
|
||||
end
|
||||
|
||||
def self.hash_from_post_ids post_ids
|
||||
hash = {}
|
||||
comments = self.on_posts(post_ids)
|
||||
post_ids.each do |id|
|
||||
hash[id] = []
|
||||
end
|
||||
comments.each do |comment|
|
||||
hash[comment.post_id] << comment
|
||||
end
|
||||
hash.each_value {|comments| comments.sort!{|c1, c2| c1.created_at <=> c2.created_at }}
|
||||
hash
|
||||
end
|
||||
|
||||
|
||||
scope :on_posts, lambda { |post_ids|
|
||||
where(:post_id.in => post_ids)
|
||||
}
|
||||
end
|
||||
|
||||
@@ -2,24 +2,19 @@
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class Contact
|
||||
include MongoMapper::Document
|
||||
class Contact < ActiveRecord::Base
|
||||
default_scope where(:pending => false)
|
||||
|
||||
key :pending, Boolean, :default => true
|
||||
|
||||
key :user_id, ObjectId
|
||||
belongs_to :user
|
||||
validates_presence_of :user
|
||||
|
||||
key :person_id, ObjectId
|
||||
belongs_to :person
|
||||
validates_presence_of :person
|
||||
validates_uniqueness_of :person_id, :scope => :user_id
|
||||
|
||||
has_many :aspect_memberships
|
||||
has_many :aspects, :through => :aspect_memberships
|
||||
validate :not_contact_for_self
|
||||
|
||||
key :aspect_ids, Array, :typecast => 'ObjectId'
|
||||
many :aspects, :in => :aspect_ids, :class_name => 'Aspect'
|
||||
validates_uniqueness_of :person_id, :scope => :user_id
|
||||
|
||||
def dispatch_request
|
||||
request = self.generate_request
|
||||
@@ -28,13 +23,26 @@ class Contact
|
||||
end
|
||||
|
||||
def generate_request
|
||||
Request.new(:from => self.user, :to => self.person)
|
||||
Request.new(:sender => self.user.person,
|
||||
:recipient => self.person,
|
||||
:aspect => aspects.first)
|
||||
end
|
||||
|
||||
def contacts
|
||||
people = Person.arel_table
|
||||
incoming_aspects = Aspect.joins(:contacts).where(
|
||||
:user_id => self.person.owner_id,
|
||||
:contacts_visible => true,
|
||||
:contacts => {:person_id => self.user.person.id}).select('`aspects`.id')
|
||||
incoming_aspect_ids = incoming_aspects.map{|a| a.id}
|
||||
similar_contacts = Person.joins(:contacts => :aspect_memberships).where(
|
||||
:aspect_memberships => {:aspect_id => incoming_aspect_ids}).where(people[:id].not_eq(self.user.person.id)).select('DISTINCT `people`.*')
|
||||
end
|
||||
private
|
||||
def not_contact_for_self
|
||||
if person.owner_id == user.id
|
||||
if person_id && person.owner == user
|
||||
errors[:base] << 'Cannot create self-contact'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
72
app/models/conversation.rb
Normal file
72
app/models/conversation.rb
Normal file
@@ -0,0 +1,72 @@
|
||||
class Conversation < ActiveRecord::Base
|
||||
include ROXML
|
||||
include Diaspora::Guid
|
||||
include Diaspora::Webhooks
|
||||
|
||||
xml_attr :subject
|
||||
xml_attr :created_at
|
||||
xml_attr :messages, :as => [Message]
|
||||
xml_reader :diaspora_handle
|
||||
xml_reader :participant_handles
|
||||
|
||||
has_many :conversation_visibilities, :dependent => :destroy
|
||||
has_many :participants, :class_name => 'Person', :through => :conversation_visibilities, :source => :person
|
||||
has_many :messages, :order => 'created_at ASC'
|
||||
|
||||
belongs_to :author, :class_name => 'Person'
|
||||
|
||||
def self.create(opts={})
|
||||
opts = opts.dup
|
||||
msg_opts = {:author => opts[:author], :text => opts.delete(:text)}
|
||||
|
||||
cnv = super(opts)
|
||||
message = Message.new(msg_opts.merge({:conversation_id => cnv.id}))
|
||||
message.save
|
||||
cnv
|
||||
end
|
||||
|
||||
def recipients
|
||||
self.participants - [self.author]
|
||||
end
|
||||
|
||||
def diaspora_handle
|
||||
self.author.diaspora_handle
|
||||
end
|
||||
def diaspora_handle= nh
|
||||
self.author = Webfinger.new(nh).fetch
|
||||
end
|
||||
|
||||
def participant_handles
|
||||
self.participants.map{|p| p.diaspora_handle}.join(";")
|
||||
end
|
||||
def participant_handles= handles
|
||||
handles.split(';').each do |handle|
|
||||
self.participants << Webfinger.new(handle).fetch
|
||||
end
|
||||
end
|
||||
|
||||
def last_author
|
||||
self.messages.last.author if self.messages.size > 0
|
||||
end
|
||||
|
||||
def subject
|
||||
self[:subject].blank? ? "no subject" : self[:subject]
|
||||
end
|
||||
|
||||
def subscribers(user)
|
||||
self.recipients
|
||||
end
|
||||
|
||||
def receive(user, person)
|
||||
cnv = Conversation.find_or_create_by_guid(self.attributes)
|
||||
|
||||
self.participants.each do |participant|
|
||||
ConversationVisibility.find_or_create_by_conversation_id_and_person_id(cnv.id, participant.id)
|
||||
end
|
||||
self.messages.each do |msg|
|
||||
msg.conversation_id = cnv.id
|
||||
received_msg = msg.receive(user, person)
|
||||
Notification.notify(user, received_msg, person) if msg.respond_to?(:notification_type)
|
||||
end
|
||||
end
|
||||
end
|
||||
6
app/models/conversation_visibility.rb
Normal file
6
app/models/conversation_visibility.rb
Normal file
@@ -0,0 +1,6 @@
|
||||
class ConversationVisibility < ActiveRecord::Base
|
||||
|
||||
belongs_to :conversation
|
||||
belongs_to :person
|
||||
|
||||
end
|
||||
@@ -2,51 +2,62 @@
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class Invitation
|
||||
include MongoMapper::Document
|
||||
class Invitation < ActiveRecord::Base
|
||||
|
||||
belongs_to :from, :class => User
|
||||
belongs_to :to, :class => User
|
||||
belongs_to :into, :class => Aspect
|
||||
key :message, String
|
||||
belongs_to :sender, :class_name => 'User'
|
||||
belongs_to :recipient, :class_name => 'User'
|
||||
belongs_to :aspect
|
||||
|
||||
validates_presence_of :from, :to, :into
|
||||
validates_presence_of :sender, :recipient, :aspect
|
||||
|
||||
def self.invite(opts = {})
|
||||
return false if opts[:email] == opts[:from].email
|
||||
existing_user = User.find_by_email(opts[:email])
|
||||
return false if opts[:identifier] == opts[:from].email
|
||||
|
||||
existing_user = self.find_existing_user(opts[:service], opts[:identifier])
|
||||
|
||||
if existing_user
|
||||
if opts[:from].contact_for(opts[:from].person)
|
||||
raise "You are already connceted to this person"
|
||||
elsif not existing_user.invited?
|
||||
opts[:from].send_contact_request_to(existing_user.person, opts[:into])
|
||||
return
|
||||
elsif Invitation.first(:from_id => opts[:from].id, :to_id => existing_user.id)
|
||||
elsif Invitation.where(:sender_id => opts[:from].id, :recipient_id => existing_user.id).first
|
||||
raise "You already invited this person"
|
||||
end
|
||||
end
|
||||
|
||||
opts[:existing_user] = existing_user
|
||||
create_invitee(opts)
|
||||
end
|
||||
|
||||
def self.new_or_existing_user_by_email(email)
|
||||
existing_user = User.first(:email => email)
|
||||
if existing_user
|
||||
existing_user
|
||||
def self.find_existing_user(service, identifier)
|
||||
existing_user = User.where(:invitation_service => service,
|
||||
:invitation_identifier => identifier).first
|
||||
if service == 'email'
|
||||
existing_user ||= User.where(:email => identifier).first
|
||||
else
|
||||
result = User.new()
|
||||
result.email = email
|
||||
result.valid?
|
||||
result
|
||||
existing_user ||= User.joins(:services).where(:services => {:type => "Services::#{service.titleize}", :uid => identifier}).first
|
||||
end
|
||||
|
||||
existing_user
|
||||
end
|
||||
|
||||
def self.new_user_by_service_and_identifier(service, identifier)
|
||||
result = User.new()
|
||||
result.invitation_service = service
|
||||
result.invitation_identifier = identifier
|
||||
result.email = identifier if service == 'email'
|
||||
result.valid?
|
||||
result
|
||||
end
|
||||
|
||||
def self.create_invitee(opts = {})
|
||||
invitee = new_or_existing_user_by_email(opts[:email])
|
||||
return invitee unless opts[:email].match Devise.email_regexp
|
||||
invitee.invites = opts[:invites]
|
||||
invitee = opts[:existing_user] || new_user_by_service_and_identifier(opts[:service], opts[:identifier])
|
||||
return invitee if opts[:service] == 'email' && !opts[:identifier].match(Devise.email_regexp)
|
||||
invitee.invites = opts[:invites] || 5
|
||||
if invitee.new_record?
|
||||
invitee.errors.clear
|
||||
invitee.serialized_private_key ||= User.generate_key
|
||||
invitee.serialized_private_key = User.generate_key if invitee.serialized_private_key.blank?
|
||||
invitee.send(:generate_invitation_token)
|
||||
elsif invitee.invitation_token.nil?
|
||||
return invitee
|
||||
@@ -54,23 +65,28 @@ class Invitation
|
||||
|
||||
if opts[:from]
|
||||
invitee.save(:validate => false)
|
||||
Invitation.create!(:from => opts[:from],
|
||||
:to => invitee,
|
||||
:into => opts[:into],
|
||||
Invitation.create!(:sender => opts[:from],
|
||||
:recipient => invitee,
|
||||
:aspect => opts[:into],
|
||||
:message => opts[:message])
|
||||
|
||||
opts[:from].invites -= 1 unless opts[:from].invites == 0
|
||||
opts[:from].save!
|
||||
invitee.reload
|
||||
end
|
||||
|
||||
invitee.invite!
|
||||
Rails.logger.info("event=invitation_sent to=#{opts[:email]} #{"inviter=#{opts[:from].diaspora_handle}" if opts[:from]}")
|
||||
invitee.invite!(:email => (opts[:service] == 'email'))
|
||||
log_string = "event=invitation_sent to=#{opts[:identifier]} service=#{opts[:service]} "
|
||||
log_string << "inviter=#{opts[:from].diaspora_handle} inviter_uid=#{opts[:from].id} inviter_created_at_unix=#{opts[:from].created_at.to_i}" if opts[:from]
|
||||
Rails.logger.info(log_string)
|
||||
invitee
|
||||
end
|
||||
|
||||
def resend
|
||||
recipient.invite!
|
||||
end
|
||||
|
||||
def to_request!
|
||||
request = from.send_contact_request_to(to.person, into)
|
||||
request = sender.send_contact_request_to(recipient.person, aspect)
|
||||
destroy if request
|
||||
request
|
||||
end
|
||||
|
||||
13
app/models/jobs/base.rb
Normal file
13
app/models/jobs/base.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
module Job
|
||||
class Base
|
||||
extend ResqueJobLogging
|
||||
|
||||
def self.perform(*args)
|
||||
ActiveRecord::Base.verify_active_connections!
|
||||
self.perform_delegate(*args)
|
||||
end
|
||||
|
||||
def self.perform_delegate(*args) # override this
|
||||
end
|
||||
end
|
||||
end
|
||||
60
app/models/jobs/http_multi.rb
Normal file
60
app/models/jobs/http_multi.rb
Normal file
@@ -0,0 +1,60 @@
|
||||
# Copyright (c) 2010, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
require 'uri'
|
||||
|
||||
module Job
|
||||
class HttpMulti < Base
|
||||
@queue = :http
|
||||
|
||||
MAX_RETRIES = 3
|
||||
OPTS = {:max_redirects => 3, :timeout => 5000, :method => :post}
|
||||
|
||||
def self.perform_delegate(user_id, enc_object_xml, person_ids, retry_count=0)
|
||||
user = User.find(user_id)
|
||||
people = Person.where(:id => person_ids)
|
||||
|
||||
salmon = Salmon::SalmonSlap.create(user, Base64.decode64(enc_object_xml))
|
||||
|
||||
failed_request_people = []
|
||||
|
||||
hydra = Typhoeus::Hydra.new
|
||||
people.each do |person|
|
||||
|
||||
url = person.receive_url
|
||||
xml = salmon.xml_for(person)
|
||||
|
||||
request = Typhoeus::Request.new(url, OPTS.merge(:params => {:xml => CGI::escape(xml)}))
|
||||
|
||||
request.on_complete do |response|
|
||||
if response.code >= 300 && response.code < 400
|
||||
if response.headers_hash['Location'] == response.request.url.sub('http://', 'https://')
|
||||
location = URI.parse(response.headers_hash['Location'])
|
||||
newuri = "#{location.scheme}://#{location.host}"
|
||||
newuri += ":#{location.port}" unless ["80", "443"].include?(location.port.to_s)
|
||||
newuri += "/"
|
||||
person.url = newuri
|
||||
person.save
|
||||
end
|
||||
end
|
||||
unless response.success?
|
||||
Rails.logger.info("event=http_multi_fail sender_id=#{user_id} recipient_id=#{person.id} url=#{response.effective_url} response_code='#{response.code}' xml='#{Base64.decode64(enc_object_xml)}'")
|
||||
failed_request_people << person.id
|
||||
end
|
||||
end
|
||||
|
||||
hydra.queue request
|
||||
end
|
||||
hydra.run
|
||||
|
||||
unless failed_request_people.empty?
|
||||
if retry_count < MAX_RETRIES
|
||||
Resque.enqueue(Job::HttpMulti, user_id, enc_object_xml, failed_request_people, retry_count + 1 )
|
||||
else
|
||||
Rails.logger.info("event=http_multi_abandon sender_id=#{user_id} failed_recipient_ids='[#{person_ids.join(', ')}] xml='#{Base64.decode64(enc_object_xml)}'")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -3,13 +3,12 @@
|
||||
# the COPYRIGHT file.
|
||||
|
||||
|
||||
module Jobs
|
||||
class HttpPost
|
||||
extend ResqueJobLogging
|
||||
module Job
|
||||
class HttpPost < Base
|
||||
@queue = :http
|
||||
NUM_TRIES = 3
|
||||
|
||||
def self.perform(url, body, tries_remaining = NUM_TRIES)
|
||||
def self.perform_delegate(url, body, tries_remaining = NUM_TRIES)
|
||||
begin
|
||||
body = CGI::escape(body)
|
||||
RestClient.post(url, :xml => body){ |response, request, result, &block|
|
||||
|
||||
@@ -3,13 +3,12 @@
|
||||
# the COPYRIGHT file.
|
||||
|
||||
|
||||
module Jobs
|
||||
class InviteUser
|
||||
extend ResqueJobLogging
|
||||
module Job
|
||||
class InviteUserByEmail < Base
|
||||
@queue = :mail
|
||||
def self.perform(sender_id, email, aspect_id, invite_message)
|
||||
def self.perform_delegate(sender_id, email, aspect_id, invite_message)
|
||||
user = User.find(sender_id)
|
||||
user.invite_user(email, aspect_id, invite_message)
|
||||
user.invite_user(aspect_id, 'email', email, invite_message)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,8 +1,7 @@
|
||||
module Jobs
|
||||
class MailAlsoCommented
|
||||
extend ResqueJobLogging
|
||||
module Job
|
||||
class MailAlsoCommented < Base
|
||||
@queue = :mail
|
||||
def self.perform(recipient_id, sender_id, comment_id)
|
||||
def self.perform_delegate(recipient_id, sender_id, comment_id)
|
||||
Notifier.also_commented(recipient_id, sender_id, comment_id).deliver
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
module Jobs
|
||||
class MailCommentOnPost
|
||||
extend ResqueJobLogging
|
||||
module Job
|
||||
class MailCommentOnPost < Base
|
||||
@queue = :mail
|
||||
def self.perform(recipient_id, sender_id, comment_id)
|
||||
def self.perform_delegate(recipient_id, sender_id, comment_id)
|
||||
Notifier.comment_on_post(recipient_id, sender_id, comment_id).deliver
|
||||
end
|
||||
end
|
||||
|
||||
15
app/models/jobs/mail_mentioned.rb
Normal file
15
app/models/jobs/mail_mentioned.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
# Copyright (c) 2010, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
|
||||
module Job
|
||||
class MailMentioned < Base
|
||||
@queue = :mail
|
||||
def self.perform_delegate(recipient_id, actor_id, target_id)
|
||||
|
||||
Notifier.mentioned( recipient_id, actor_id, target_id).deliver
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
13
app/models/jobs/mail_private_message.rb
Normal file
13
app/models/jobs/mail_private_message.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2010, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
|
||||
module Job
|
||||
class MailPrivateMessage < Base
|
||||
@queue = :mail
|
||||
def self.perform_delegate(recipient_id, actor_id, target_id)
|
||||
Notifier.private_message( recipient_id, actor_id, target_id).deliver
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -3,11 +3,10 @@
|
||||
# the COPYRIGHT file.
|
||||
|
||||
|
||||
module Jobs
|
||||
class MailRequestAcceptance
|
||||
extend ResqueJobLogging
|
||||
module Job
|
||||
class MailRequestAcceptance < Base
|
||||
@queue = :mail
|
||||
def self.perform(recipient_id, sender_id)
|
||||
def self.perform_delegate(recipient_id, sender_id, target_id)
|
||||
Notifier.request_accepted(recipient_id, sender_id).deliver
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
# the COPYRIGHT file.
|
||||
|
||||
|
||||
module Jobs
|
||||
class MailRequestReceived
|
||||
extend ResqueJobLogging
|
||||
module Job
|
||||
class MailRequestReceived < Base
|
||||
@queue = :mail
|
||||
def self.perform(recipient_id, sender_id)
|
||||
def self.perform_delegate(recipient_id, sender_id, target_id)
|
||||
Notifier.new_request(recipient_id, sender_id).deliver
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,14 +2,13 @@
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
module Jobs
|
||||
class NotifyLocalUsers
|
||||
extend ResqueJobLogging
|
||||
module Job
|
||||
class NotifyLocalUsers < Base
|
||||
@queue = :receive_local
|
||||
|
||||
require File.join(Rails.root, 'app/models/notification')
|
||||
|
||||
def self.perform(user_id, object_klass, object_id, person_id)
|
||||
def self.perform_delegate(user_id, object_klass, object_id, person_id)
|
||||
user = User.find_by_id(user_id)
|
||||
object = object_klass.constantize.find_by_id(object_id)
|
||||
person = Person.find_by_id(person_id)
|
||||
|
||||
@@ -2,12 +2,11 @@
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
#
|
||||
module Jobs
|
||||
class PostToService
|
||||
extend ResqueJobLogging
|
||||
module Job
|
||||
class PostToService < Base
|
||||
@queue = :http_service
|
||||
|
||||
def self.perform(service_id, post_id, url)
|
||||
def self.perform_delegate(service_id, post_id, url)
|
||||
service = Service.find_by_id(service_id)
|
||||
post = Post.find_by_id(post_id)
|
||||
service.post(post, url)
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
# Copyright (c) 2010, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
|
||||
module Jobs
|
||||
class PostToServices
|
||||
extend ResqueJobLogging
|
||||
@queue = :http_service
|
||||
def self.perform(user_id, post_id, url)
|
||||
user = User.find_by_id(user_id)
|
||||
post = Post.find_by_id(post_id)
|
||||
user.services.each do |s|
|
||||
s.post(post, url)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -2,12 +2,11 @@
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
module Jobs
|
||||
class PublishToHub
|
||||
extend ResqueJobLogging
|
||||
module Job
|
||||
class PublishToHub < Base
|
||||
@queue = :http_service
|
||||
|
||||
def self.perform(sender_public_url)
|
||||
def self.perform_delegate(sender_public_url)
|
||||
require File.join(Rails.root, 'lib/pubsubhubbub')
|
||||
Pubsubhubbub.new(AppConfig[:pubsub_server]).publish(sender_public_url)
|
||||
end
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
# the COPYRIGHT file.
|
||||
|
||||
|
||||
module Jobs
|
||||
class Receive
|
||||
extend ResqueJobLogging
|
||||
module Job
|
||||
class Receive < Base
|
||||
|
||||
@queue = :receive
|
||||
def self.perform(user_id, xml, salmon_author_id)
|
||||
user = User.find(user_id)
|
||||
|
||||
@@ -3,16 +3,15 @@
|
||||
# the COPYRIGHT file.
|
||||
|
||||
|
||||
module Jobs
|
||||
class ReceiveLocal
|
||||
module Job
|
||||
class ReceiveLocal < Base
|
||||
require File.join(Rails.root, 'lib/postzord/receiver')
|
||||
|
||||
extend ResqueJobLogging
|
||||
@queue = :receive_local
|
||||
def self.perform(user_id, person_id, object_type, object_id)
|
||||
def self.perform_delegate(user_id, person_id, object_type, object_id)
|
||||
user = User.find(user_id)
|
||||
person = Person.find(person_id)
|
||||
object = object_type.constantize.first(:id => object_id)
|
||||
object = object_type.constantize.where(:id => object_id).first
|
||||
|
||||
z = Postzord::Receiver.new(user, :person => person, :object => object)
|
||||
z.receive_object
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
|
||||
|
||||
require File.join(Rails.root, 'lib/postzord/receiver')
|
||||
module Jobs
|
||||
class ReceiveSalmon
|
||||
extend ResqueJobLogging
|
||||
module Job
|
||||
class ReceiveSalmon < Base
|
||||
@queue = :receive_salmon
|
||||
def self.perform(user_id, xml)
|
||||
|
||||
def self.perform_delegate(user_id, xml)
|
||||
user = User.find(user_id)
|
||||
zord = Postzord::Receiver.new(user, :salmon_xml => xml)
|
||||
zord.perform
|
||||
|
||||
14
app/models/jobs/resend_invitation.rb
Normal file
14
app/models/jobs/resend_invitation.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
# Copyright (c) 2010, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
|
||||
module Job
|
||||
class ResendInvitation < Base
|
||||
@queue = :mail
|
||||
def self.perform_delegate(invitation_id)
|
||||
inv = Invitation.where(:id => invitation_id).first
|
||||
inv.resend
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -3,16 +3,17 @@
|
||||
# the COPYRIGHT file.
|
||||
|
||||
|
||||
module Jobs
|
||||
class SocketWebfinger
|
||||
extend ResqueJobLogging
|
||||
module Job
|
||||
class SocketWebfinger < Base
|
||||
|
||||
@queue = :socket_webfinger
|
||||
def self.perform(user_id, account, opts={})
|
||||
|
||||
def self.perform_delegate(user_id, account, opts={})
|
||||
finger = Webfinger.new(account)
|
||||
begin
|
||||
user = User.find_by_id(user_id)
|
||||
result = finger.fetch
|
||||
result.socket_to_uid(user, opts)
|
||||
result.socket_to_user(user, opts)
|
||||
rescue
|
||||
Diaspora::WebSocket.queue_to_user(user_id,
|
||||
{:class => 'people',
|
||||
|
||||
25
app/models/mention.rb
Normal file
25
app/models/mention.rb
Normal file
@@ -0,0 +1,25 @@
|
||||
# Copyright (c) 2010, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class Mention < ActiveRecord::Base
|
||||
belongs_to :post
|
||||
belongs_to :person
|
||||
validates_presence_of :post
|
||||
validates_presence_of :person
|
||||
|
||||
after_destroy :delete_notification
|
||||
|
||||
def notify_recipient
|
||||
Rails.logger.info "event=mention_sent id=#{self.id} to=#{person.diaspora_handle} from=#{post.author.diaspora_handle}"
|
||||
Notification.notify(person.owner, self, post.author) unless person.remote?
|
||||
end
|
||||
|
||||
def notification_type(*args)
|
||||
Notifications::Mentioned
|
||||
end
|
||||
|
||||
def delete_notification
|
||||
Notification.where(:target_type => self.class.name, :target_id => self.id).delete_all
|
||||
end
|
||||
end
|
||||
82
app/models/message.rb
Normal file
82
app/models/message.rb
Normal file
@@ -0,0 +1,82 @@
|
||||
class Message < ActiveRecord::Base
|
||||
include ROXML
|
||||
|
||||
include Diaspora::Guid
|
||||
include Diaspora::Webhooks
|
||||
include Diaspora::Relayable
|
||||
|
||||
xml_attr :text
|
||||
xml_attr :created_at
|
||||
xml_reader :diaspora_handle
|
||||
xml_reader :conversation_guid
|
||||
|
||||
belongs_to :author, :class_name => 'Person'
|
||||
belongs_to :conversation, :touch => true
|
||||
|
||||
after_create do
|
||||
#sign comment as commenter
|
||||
self.author_signature = self.sign_with_key(self.author.owner.encryption_key) if self.author.owner
|
||||
|
||||
if !self.parent.blank? && self.author.owns?(self.parent)
|
||||
#sign comment as post owner
|
||||
self.parent_author_signature = self.sign_with_key( self.parent.author.owner.encryption_key) if self.parent.author.owner
|
||||
end
|
||||
self.save!
|
||||
self
|
||||
end
|
||||
|
||||
validate :participant_of_parent_conversation
|
||||
|
||||
def diaspora_handle
|
||||
self.author.diaspora_handle
|
||||
end
|
||||
|
||||
def diaspora_handle= nh
|
||||
self.author = Webfinger.new(nh).fetch
|
||||
end
|
||||
|
||||
def conversation_guid
|
||||
self.conversation.guid
|
||||
end
|
||||
|
||||
def conversation_guid= guid
|
||||
if cnv = Conversation.find_by_guid(guid)
|
||||
self.conversation_id = cnv.id
|
||||
end
|
||||
end
|
||||
|
||||
def parent_class
|
||||
Conversation
|
||||
end
|
||||
|
||||
def parent
|
||||
self.conversation
|
||||
end
|
||||
|
||||
def parent= parent
|
||||
self.conversation = parent
|
||||
end
|
||||
|
||||
def after_receive(user, person)
|
||||
if vis = ConversationVisibility.where(:conversation_id => self.conversation_id, :person_id => user.person.id).first
|
||||
vis.unread += 1
|
||||
vis.save
|
||||
self
|
||||
else
|
||||
raise NotVisibileException("Attempting to access a ConversationVisibility that does not exist!")
|
||||
end
|
||||
end
|
||||
|
||||
def notification_type(user, person)
|
||||
Notifications::PrivateMessage unless user.person == person
|
||||
end
|
||||
|
||||
private
|
||||
def participant_of_parent_conversation
|
||||
if self.parent && !self.parent.participants.include?(self.author)
|
||||
errors[:base] << "Author is not participating in the conversation"
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
21
app/models/mongo.rb
Normal file
21
app/models/mongo.rb
Normal file
@@ -0,0 +1,21 @@
|
||||
module Mongo
|
||||
def self.table_name_prefix
|
||||
"mongo_"
|
||||
end
|
||||
|
||||
class Aspect < ActiveRecord::Base; end
|
||||
class AspectMembership < ActiveRecord::Base; end
|
||||
class Comment < ActiveRecord::Base; end
|
||||
class Contact < ActiveRecord::Base; end
|
||||
class Invitation < ActiveRecord::Base; end
|
||||
class Notification < ActiveRecord::Base; end
|
||||
class Person < ActiveRecord::Base; end
|
||||
#Photo?
|
||||
class Post < ActiveRecord::Base; end
|
||||
class PostVisibility < ActiveRecord::Base; end
|
||||
class Profile < ActiveRecord::Base; end
|
||||
class Request < ActiveRecord::Base; end
|
||||
class Service < ActiveRecord::Base; end
|
||||
#StatusMessage?
|
||||
class User < ActiveRecord::Base; end
|
||||
end
|
||||
@@ -2,50 +2,64 @@
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
#
|
||||
class Notification
|
||||
class Notification < ActiveRecord::Base
|
||||
require File.join(Rails.root, 'lib/diaspora/web_socket')
|
||||
include MongoMapper::Document
|
||||
include Diaspora::Socketable
|
||||
|
||||
key :target_id, ObjectId
|
||||
key :kind, String
|
||||
key :unread, Boolean, :default => true
|
||||
belongs_to :recipient, :class_name => 'User'
|
||||
has_many :notification_actors
|
||||
has_many :actors, :class_name => 'Person', :through => :notification_actors, :source => :person
|
||||
belongs_to :target, :polymorphic => true
|
||||
|
||||
belongs_to :user
|
||||
belongs_to :person
|
||||
|
||||
timestamps!
|
||||
|
||||
attr_accessible :target_id, :kind, :user_id, :person_id, :unread
|
||||
|
||||
def self.for(user, opts={})
|
||||
self.where(opts.merge!(:user_id => user.id)).order('created_at desc')
|
||||
def self.for(recipient, opts={})
|
||||
self.where(opts.merge!(:recipient_id => recipient.id)).order('updated_at desc')
|
||||
end
|
||||
|
||||
def self.notify(user, object, person)
|
||||
if object.respond_to? :notification_type
|
||||
if kind = object.notification_type(user, person)
|
||||
n = Notification.create(:target_id => object.id,
|
||||
:kind => kind,
|
||||
:person_id => person.id,
|
||||
:user_id => user.id)
|
||||
n.email_the_user(object) if n
|
||||
n.socket_to_uid(user) if n
|
||||
def self.notify(recipient, target, actor)
|
||||
if target.respond_to? :notification_type
|
||||
if note_type = target.notification_type(recipient, actor)
|
||||
if target.is_a? Comment
|
||||
n = note_type.concatenate_or_create(recipient, target.post, actor, note_type)
|
||||
else
|
||||
n = note_type.make_notification(recipient, target, actor, note_type)
|
||||
end
|
||||
n.email_the_user(target, actor) if n
|
||||
n.socket_to_user(recipient, :actor => actor) if n
|
||||
n
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def email_the_user(object)
|
||||
case self.kind
|
||||
when "new_request"
|
||||
self.user.mail(Jobs::MailRequestReceived, self.user_id, self.person_id)
|
||||
when "request_accepted"
|
||||
self.user.mail(Jobs::MailRequestAcceptance, self.user_id, self.person_id)
|
||||
when "comment_on_post"
|
||||
self.user.mail(Jobs::MailCommentOnPost, self.user_id, self.person_id, object.id)
|
||||
when "also_commented"
|
||||
self.user.mail(Jobs::MailAlsoCommented, self.user_id, self.person_id, object.id)
|
||||
def email_the_user(target, actor)
|
||||
self.recipient.mail(self.mail_job, self.recipient_id, actor.id, target.id)
|
||||
end
|
||||
def mail_job
|
||||
raise NotImplementedError.new('Subclass this.')
|
||||
end
|
||||
|
||||
private
|
||||
def self.concatenate_or_create(recipient, target, actor, notification_type)
|
||||
if n = notification_type.where(:target_id => target.id,
|
||||
:target_type => target.class.base_class,
|
||||
:recipient_id => recipient.id).first
|
||||
unless n.actors.include?(actor)
|
||||
n.actors << actor
|
||||
end
|
||||
|
||||
n.unread = true
|
||||
n.save!
|
||||
n
|
||||
else
|
||||
make_notification(recipient, target, actor, notification_type)
|
||||
end
|
||||
end
|
||||
|
||||
def self.make_notification(recipient, target, actor, notification_type)
|
||||
n = notification_type.new(:target => target,
|
||||
:recipient_id => recipient.id)
|
||||
n.actors << actor
|
||||
n.unread = false if target.is_a? Request
|
||||
n.save!
|
||||
n
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
require 'spec_helper'
|
||||
class NotificationActor < ActiveRecord::Base
|
||||
|
||||
describe RequestsHelper do
|
||||
belongs_to :notification
|
||||
belongs_to :person
|
||||
|
||||
end
|
||||
8
app/models/notifications/also_commented.rb
Normal file
8
app/models/notifications/also_commented.rb
Normal file
@@ -0,0 +1,8 @@
|
||||
class Notifications::AlsoCommented < Notification
|
||||
def mail_job
|
||||
Job::MailAlsoCommented
|
||||
end
|
||||
def translation_key
|
||||
'also_commented'
|
||||
end
|
||||
end
|
||||
8
app/models/notifications/comment_on_post.rb
Normal file
8
app/models/notifications/comment_on_post.rb
Normal file
@@ -0,0 +1,8 @@
|
||||
class Notifications::CommentOnPost < Notification
|
||||
def mail_job
|
||||
Job::MailCommentOnPost
|
||||
end
|
||||
def translation_key
|
||||
'comment_on_post'
|
||||
end
|
||||
end
|
||||
8
app/models/notifications/mentioned.rb
Normal file
8
app/models/notifications/mentioned.rb
Normal file
@@ -0,0 +1,8 @@
|
||||
class Notifications::Mentioned < Notification
|
||||
def mail_job
|
||||
Job::MailMentioned
|
||||
end
|
||||
def translation_key
|
||||
'mentioned'
|
||||
end
|
||||
end
|
||||
8
app/models/notifications/new_request.rb
Normal file
8
app/models/notifications/new_request.rb
Normal file
@@ -0,0 +1,8 @@
|
||||
class Notifications::NewRequest < Notification
|
||||
def mail_job
|
||||
Job::MailRequestReceived
|
||||
end
|
||||
def translation_key
|
||||
'new_request'
|
||||
end
|
||||
end
|
||||
15
app/models/notifications/private_message.rb
Normal file
15
app/models/notifications/private_message.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
class Notifications::PrivateMessage < Notification
|
||||
def mail_job
|
||||
Job::MailPrivateMessage
|
||||
end
|
||||
def translation_key
|
||||
'private_message'
|
||||
end
|
||||
def self.make_notification(recipient, target, actor, notification_type)
|
||||
n = notification_type.new(:target => target,
|
||||
:recipient_id => recipient.id)
|
||||
|
||||
n.actors << actor
|
||||
n
|
||||
end
|
||||
end
|
||||
8
app/models/notifications/request_accepted.rb
Normal file
8
app/models/notifications/request_accepted.rb
Normal file
@@ -0,0 +1,8 @@
|
||||
class Notifications::RequestAccepted < Notification
|
||||
def mail_job
|
||||
Job::MailRequestAcceptance
|
||||
end
|
||||
def translation_key
|
||||
'request_accepted'
|
||||
end
|
||||
end
|
||||
@@ -2,98 +2,126 @@
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
require 'uri'
|
||||
require File.join(Rails.root, 'lib/hcard')
|
||||
|
||||
class Person
|
||||
include MongoMapper::Document
|
||||
class Person < ActiveRecord::Base
|
||||
include ROXML
|
||||
include Encryptor::Public
|
||||
require File.join(Rails.root, 'lib/diaspora/web_socket')
|
||||
include Diaspora::Socketable
|
||||
include Diaspora::Guid
|
||||
|
||||
xml_accessor :_id
|
||||
xml_accessor :diaspora_handle
|
||||
xml_accessor :url
|
||||
xml_accessor :profile, :as => Profile
|
||||
xml_reader :exported_key
|
||||
xml_attr :diaspora_handle
|
||||
xml_attr :url
|
||||
xml_attr :profile, :as => Profile
|
||||
xml_attr :exported_key
|
||||
|
||||
key :url, String
|
||||
key :diaspora_handle, String, :unique => true
|
||||
key :serialized_public_key, String
|
||||
|
||||
key :owner_id, ObjectId
|
||||
|
||||
one :profile, :class_name => 'Profile'
|
||||
validates_associated :profile
|
||||
has_one :profile
|
||||
delegate :last_name, :to => :profile
|
||||
before_save :downcase_diaspora_handle
|
||||
|
||||
before_save :downcase_diaspora_handle
|
||||
def downcase_diaspora_handle
|
||||
diaspora_handle.downcase!
|
||||
end
|
||||
|
||||
has_many :contacts #Other people's contacts for this person
|
||||
has_many :posts, :foreign_key => :author_id #his own posts
|
||||
|
||||
belongs_to :owner, :class_name => 'User'
|
||||
|
||||
timestamps!
|
||||
has_many :notification_actors
|
||||
has_many :notifications, :through => :notification_actors
|
||||
|
||||
has_many :mentions, :dependent => :destroy
|
||||
|
||||
before_destroy :remove_all_traces
|
||||
before_validation :clean_url
|
||||
|
||||
validates_presence_of :url, :profile, :serialized_public_key
|
||||
validates_uniqueness_of :diaspora_handle, :case_sensitive => false
|
||||
#validates_format_of :url, :with =>
|
||||
# /^(https?):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*(\.[a-z]{2,5})?(:[0-9]{1,5})?(\/.*)?$/ix
|
||||
|
||||
ensure_index :diaspora_handle
|
||||
scope :searchable, joins(:profile).where(:profiles => {:searchable => true})
|
||||
|
||||
scope :searchable, where('profile.searchable' => true)
|
||||
def self.search(query, user)
|
||||
return [] if query.to_s.blank? || query.to_s.length < 3
|
||||
|
||||
attr_accessible :profile
|
||||
where_clause = <<-SQL
|
||||
profiles.first_name LIKE ? OR
|
||||
profiles.last_name LIKE ? OR
|
||||
people.diaspora_handle LIKE ? OR
|
||||
profiles.first_name LIKE ? OR
|
||||
profiles.last_name LIKE ?
|
||||
SQL
|
||||
sql = ""
|
||||
tokens = []
|
||||
|
||||
def self.search(query)
|
||||
return [] if query.to_s.empty?
|
||||
query_tokens = query.to_s.strip.split(" ")
|
||||
full_query_text = Regexp.escape(query.to_s.strip)
|
||||
|
||||
p = []
|
||||
|
||||
query_tokens.each do |token|
|
||||
q = Regexp.escape(token.to_s.strip)
|
||||
p = Person.searchable.all('profile.first_name' => /^#{q}/i, 'limit' => 30) \
|
||||
| Person.searchable.all('profile.last_name' => /^#{q}/i, 'limit' => 30) \
|
||||
| Person.searchable.all('diaspora_handle' => /^#{q}/i, 'limit' => 30) \
|
||||
| p
|
||||
query_tokens.each_with_index do |raw_token, i|
|
||||
token = "#{raw_token}%"
|
||||
up_token = "#{raw_token.titleize}%"
|
||||
sql << " OR " unless i == 0
|
||||
sql << where_clause
|
||||
tokens.concat([token, token, token])
|
||||
tokens.concat([up_token, up_token])
|
||||
end
|
||||
|
||||
return p
|
||||
#SELECT `people`.* FROM people
|
||||
# INNER JOIN `profiles` ON `profiles`.person_id = `people`.id
|
||||
# LEFT OUTER JOIN `contacts` ON (`contacts`.user_id = #{user.id} AND `contacts`.person_id = `people`.id)
|
||||
# WHERE `profiles`.searchable = true AND
|
||||
# `profiles`.first_name LIKE '%Max%'
|
||||
# ORDER BY `contacts`.user_id DESC
|
||||
Person.searchable.where(sql, *tokens).joins(
|
||||
"LEFT OUTER JOIN `contacts` ON `contacts`.user_id = #{user.id} AND `contacts`.person_id = `people`.id"
|
||||
).joins("LEFT OUTER JOIN `requests` ON `requests`.recipient_id = #{user.person.id} AND `requests`.sender_id = `people`.id"
|
||||
).order("contacts.user_id DESC", "requests.recipient_id DESC", "profiles.last_name ASC", "profiles.first_name ASC")
|
||||
end
|
||||
|
||||
def name
|
||||
@name ||= if profile.first_name.nil? || profile.first_name.blank?
|
||||
def name(opts = {})
|
||||
@name ||= if profile.nil? || profile.first_name.nil? || profile.first_name.blank?
|
||||
self.diaspora_handle
|
||||
else
|
||||
"#{profile.first_name.to_s} #{profile.last_name.to_s}"
|
||||
end
|
||||
end
|
||||
|
||||
def first_name
|
||||
@first_name ||= if profile.first_name.nil? || profile.first_name.blank?
|
||||
@first_name ||= if profile.nil? || profile.first_name.nil? || profile.first_name.blank?
|
||||
self.diaspora_handle.split('@').first
|
||||
else
|
||||
profile.first_name.to_s
|
||||
end
|
||||
end
|
||||
def owns?(post)
|
||||
self.id == post.person.id
|
||||
|
||||
def owns?(obj)
|
||||
self == obj.author
|
||||
end
|
||||
|
||||
def url
|
||||
begin
|
||||
uri = URI.parse(@attributes['url'])
|
||||
url = "#{uri.scheme}://#{uri.host}"
|
||||
url += ":#{uri.port}" unless ["80", "443"].include?(uri.port.to_s)
|
||||
url += "/"
|
||||
rescue Exception => e
|
||||
url = @attributes['url']
|
||||
end
|
||||
url
|
||||
end
|
||||
|
||||
def receive_url
|
||||
"#{self.url}receive/users/#{self.id}/"
|
||||
"#{url}receive/users/#{self.guid}/"
|
||||
end
|
||||
|
||||
def public_url
|
||||
"#{self.url}public/#{self.owner.username}"
|
||||
if self.owner
|
||||
username = self.owner.username
|
||||
else
|
||||
username = self.diaspora_handle.split("@")[0]
|
||||
end
|
||||
"#{url}public/#{username}"
|
||||
end
|
||||
|
||||
|
||||
def public_key_hash
|
||||
Base64.encode64 OpenSSL::Digest::SHA256.new(self.exported_key).to_s
|
||||
end
|
||||
@@ -108,13 +136,13 @@ class Person
|
||||
|
||||
def exported_key= new_key
|
||||
raise "Don't change a key" if serialized_public_key
|
||||
@serialized_public_key = new_key
|
||||
serialized_public_key = new_key
|
||||
end
|
||||
|
||||
#database calls
|
||||
def self.by_account_identifier(identifier)
|
||||
identifier = identifier.strip.downcase.gsub('acct:', '')
|
||||
self.first(:diaspora_handle => identifier)
|
||||
self.where(:diaspora_handle => identifier).first
|
||||
end
|
||||
|
||||
def self.local_by_account_identifier(identifier)
|
||||
@@ -125,46 +153,34 @@ class Person
|
||||
def self.create_from_webfinger(profile, hcard)
|
||||
return nil if profile.nil? || !profile.valid_diaspora_profile?
|
||||
new_person = Person.new
|
||||
new_person.exported_key = profile.public_key
|
||||
new_person.id = profile.guid
|
||||
new_person.serialized_public_key = profile.public_key
|
||||
new_person.guid = profile.guid
|
||||
new_person.diaspora_handle = profile.account
|
||||
new_person.url = profile.seed_location
|
||||
|
||||
#hcard_profile = HCard.find profile.hcard.first[:href]
|
||||
Rails.logger.info("event=webfinger_marshal valid=#{new_person.valid?} target=#{new_person.diaspora_handle}")
|
||||
new_person.url = hcard[:url]
|
||||
new_person.profile = Profile.new( :first_name => hcard[:given_name],
|
||||
:last_name => hcard[:family_name],
|
||||
:image_url => hcard[:photo],
|
||||
:image_url_medium => hcard[:photo_medium],
|
||||
:image_url_small => hcard[:photo_small],
|
||||
:searchable => hcard[:searchable])
|
||||
|
||||
new_person.save! ? new_person : nil
|
||||
new_person.profile = Profile.new(:first_name => hcard[:given_name],
|
||||
:last_name => hcard[:family_name],
|
||||
:image_url => hcard[:photo],
|
||||
:image_url_medium => hcard[:photo_medium],
|
||||
:image_url_small => hcard[:photo_small],
|
||||
:searchable => hcard[:searchable])
|
||||
new_person.save!
|
||||
new_person.profile.save!
|
||||
new_person
|
||||
end
|
||||
|
||||
def remote?
|
||||
owner_id.nil?
|
||||
end
|
||||
|
||||
def as_json(opts={})
|
||||
{
|
||||
:person => {
|
||||
:id => self.id,
|
||||
:name => self.name,
|
||||
:url => self.url,
|
||||
:exported_key => exported_key,
|
||||
:diaspora_handle => self.diaspora_handle
|
||||
}
|
||||
}
|
||||
def local?
|
||||
!remote?
|
||||
end
|
||||
|
||||
def self.from_post_comment_hash(hash)
|
||||
person_ids = hash.values.flatten.map!{|c| c.person_id}.uniq
|
||||
people = where(:id.in => person_ids).fields(:profile, :diaspora_handle)
|
||||
people_hash = {}
|
||||
people.each{|p| people_hash[p.id] = p}
|
||||
people_hash
|
||||
def as_json(opts={})
|
||||
{:id => self.guid, :name => self.name, :avatar => self.profile.image_url(:thumb_small), :handle => self.diaspora_handle, :url => "/people/#{self.id}"}
|
||||
end
|
||||
|
||||
protected
|
||||
@@ -179,8 +195,6 @@ class Person
|
||||
|
||||
private
|
||||
def remove_all_traces
|
||||
Post.where(:person_id => id).each { |p| p.delete }
|
||||
Contact.where(:person_id => id).each { |c| c.delete }
|
||||
Notification.where(:person_id => id).each { |n| n.delete }
|
||||
Notification.joins(:notification_actors).where(:notification_actors => {:person_id => self.id}).all.each{ |n| n.destroy}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,22 +3,14 @@
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class Photo < Post
|
||||
require 'carrierwave/orm/mongomapper'
|
||||
include MongoMapper::Document
|
||||
require 'carrierwave/orm/activerecord'
|
||||
mount_uploader :image, ImageUploader
|
||||
|
||||
xml_accessor :remote_photo
|
||||
xml_accessor :caption
|
||||
xml_reader :status_message_id
|
||||
xml_attr :remote_photo_path
|
||||
xml_attr :remote_photo_name
|
||||
|
||||
key :caption, String
|
||||
key :remote_photo_path
|
||||
key :remote_photo_name
|
||||
key :random_string
|
||||
|
||||
key :status_message_id, ObjectId
|
||||
|
||||
timestamps!
|
||||
xml_attr :caption
|
||||
xml_attr :status_message_guid
|
||||
|
||||
belongs_to :status_message
|
||||
|
||||
@@ -27,7 +19,6 @@ class Photo < Post
|
||||
|
||||
before_destroy :ensure_user_picture
|
||||
|
||||
#before_destroy :delete_parent_if_no_photos_or_message
|
||||
def ownership_of_status_message
|
||||
message = StatusMessage.find_by_id(self.status_message_id)
|
||||
if status_message_id && message
|
||||
@@ -37,38 +28,54 @@ class Photo < Post
|
||||
end
|
||||
end
|
||||
|
||||
def self.instantiate(params = {})
|
||||
def self.diaspora_initialize(params = {})
|
||||
photo = super(params)
|
||||
image_file = params.delete(:user_file)
|
||||
photo.random_string = gen_random_string(10)
|
||||
|
||||
photo.image.store! image_file
|
||||
|
||||
unless photo.image.url.match(/^https?:\/\//)
|
||||
pod_url = AppConfig[:pod_url].dup
|
||||
pod_url.chop! if AppConfig[:pod_url][-1,1] == '/'
|
||||
remote_path = "#{pod_url}#{photo.image.url}"
|
||||
else
|
||||
remote_path = photo.image.url
|
||||
end
|
||||
|
||||
name_start = remote_path.rindex '/'
|
||||
photo.remote_photo_path = "#{remote_path.slice(0, name_start)}/"
|
||||
photo.remote_photo_name = remote_path.slice(name_start + 1, remote_path.length)
|
||||
|
||||
photo
|
||||
end
|
||||
|
||||
def remote_photo
|
||||
image.url.nil? ? (remote_photo_path + '/' + remote_photo_name) : image.url
|
||||
def status_message_guid
|
||||
if self.status_message
|
||||
self.status_message.guid
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def remote_photo= remote_path
|
||||
name_start = remote_path.rindex '/'
|
||||
self.remote_photo_path = remote_path.slice(0, name_start )
|
||||
self.remote_photo_name = remote_path.slice(name_start + 1, remote_path.length)
|
||||
def status_message_guid= new_sm_guid
|
||||
self.status_message= StatusMessage.where(:guid => new_sm_guid).first
|
||||
end
|
||||
|
||||
def url(name = nil)
|
||||
if remote_photo_path
|
||||
name = name.to_s + "_" if name
|
||||
person.url.chop + remote_photo_path + "/" + name.to_s + remote_photo_name
|
||||
name = name.to_s + '_' if name
|
||||
remote_photo_path + name.to_s + remote_photo_name
|
||||
else
|
||||
image.url name
|
||||
image.url(name)
|
||||
end
|
||||
end
|
||||
|
||||
def ensure_user_picture
|
||||
people = Person.all('profile.image_url' => absolute_url(:thumb_large) )
|
||||
people.each{ |person|
|
||||
person.profile.update_attributes(:image_url => nil)
|
||||
profiles = Profile.where(:image_url => url(:thumb_large))
|
||||
profiles.each { |profile|
|
||||
profile.image_url = nil
|
||||
profile.save
|
||||
}
|
||||
end
|
||||
|
||||
@@ -80,12 +87,6 @@ class Photo < Post
|
||||
true
|
||||
end
|
||||
|
||||
def absolute_url *args
|
||||
pod_url = AppConfig[:pod_url].dup
|
||||
pod_url.chop! if AppConfig[:pod_url][-1,1] == '/'
|
||||
"#{pod_url}#{url(*args)}"
|
||||
end
|
||||
|
||||
def self.gen_random_string(len)
|
||||
chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
|
||||
string = ""
|
||||
@@ -93,10 +94,11 @@ class Photo < Post
|
||||
return string
|
||||
end
|
||||
|
||||
|
||||
def as_json(opts={})
|
||||
{
|
||||
:photo => {
|
||||
:id => self.id,
|
||||
:photo => {
|
||||
:id => self.id,
|
||||
:url => self.url(:thumb_medium),
|
||||
:thumb_small => self.url(:thumb_small),
|
||||
:caption => self.caption
|
||||
@@ -104,22 +106,7 @@ class Photo < Post
|
||||
}
|
||||
end
|
||||
|
||||
def self.hash_from_post_ids post_ids
|
||||
hash = {}
|
||||
photos = self.on_statuses(post_ids)
|
||||
post_ids.each do |id|
|
||||
hash[id] = []
|
||||
end
|
||||
photos.each do |photo|
|
||||
hash[photo.status_message_id] << photo
|
||||
end
|
||||
hash.each_value {|photos| photos.sort!{|p1, p2| p1.created_at <=> p2.created_at }}
|
||||
hash
|
||||
end
|
||||
scope :on_statuses, lambda { |post_ids|
|
||||
where(:status_message_id.in => post_ids)
|
||||
where(:status_message_id => post_ids)
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -2,57 +2,52 @@
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class Post
|
||||
require File.join(Rails.root, 'lib/encryptable')
|
||||
class Post < ActiveRecord::Base
|
||||
require File.join(Rails.root, 'lib/diaspora/web_socket')
|
||||
include MongoMapper::Document
|
||||
include ApplicationHelper
|
||||
include ROXML
|
||||
include Diaspora::Webhooks
|
||||
include Diaspora::Guid
|
||||
|
||||
xml_reader :_id
|
||||
xml_reader :diaspora_handle
|
||||
xml_reader :public
|
||||
xml_reader :created_at
|
||||
xml_attr :diaspora_handle
|
||||
xml_attr :public
|
||||
xml_attr :created_at
|
||||
|
||||
|
||||
key :public, Boolean, :default => false
|
||||
|
||||
key :diaspora_handle, String
|
||||
key :user_refs, Integer, :default => 0
|
||||
key :pending, Boolean, :default => false
|
||||
key :aspect_ids, Array, :typecast => 'ObjectId'
|
||||
|
||||
many :comments, :class_name => 'Comment', :foreign_key => :post_id, :order => 'created_at ASC'
|
||||
many :aspects, :in => :aspect_ids, :class_name => 'Aspect'
|
||||
belongs_to :person, :class_name => 'Person'
|
||||
|
||||
timestamps!
|
||||
has_many :comments, :order => 'created_at ASC'
|
||||
has_many :post_visibilities
|
||||
has_many :aspects, :through => :post_visibilities
|
||||
has_many :mentions, :dependent => :destroy
|
||||
belongs_to :author, :class_name => 'Person'
|
||||
|
||||
cattr_reader :per_page
|
||||
@@per_page = 10
|
||||
|
||||
before_destroy :propogate_retraction
|
||||
after_destroy :destroy_comments
|
||||
after_destroy :propogate_retraction
|
||||
|
||||
attr_accessible :user_refs
|
||||
|
||||
def self.instantiate params
|
||||
def user_refs
|
||||
self.post_visibilities.count
|
||||
end
|
||||
|
||||
def diaspora_handle= nd
|
||||
self.author = Person.where(:diaspora_handle => nd).first
|
||||
write_attribute(:diaspora_handle, nd)
|
||||
end
|
||||
|
||||
def self.diaspora_initialize params
|
||||
new_post = self.new params.to_hash
|
||||
new_post.person = params[:person]
|
||||
new_post.aspect_ids = params[:aspect_ids]
|
||||
new_post.public = params[:public]
|
||||
new_post.pending = params[:pending]
|
||||
new_post.diaspora_handle = new_post.person.diaspora_handle
|
||||
new_post.author = params[:author]
|
||||
new_post.public = params[:public] if params[:public]
|
||||
new_post.pending = params[:pending] if params[:pending]
|
||||
new_post.diaspora_handle = new_post.author.diaspora_handle
|
||||
new_post
|
||||
end
|
||||
|
||||
def as_json(opts={})
|
||||
{
|
||||
:post => {
|
||||
:id => self.id,
|
||||
:person => self.person.as_json,
|
||||
}
|
||||
:post => {
|
||||
:id => self.id,
|
||||
:author => self.author.as_json,
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
@@ -67,42 +62,39 @@ class Post
|
||||
def receive(user, person)
|
||||
#exists locally, but you dont know about it
|
||||
#does not exsist locally, and you dont know about it
|
||||
|
||||
#exists_locally?
|
||||
#you know about it, and it is mutable
|
||||
#you know about it, and it is not mutable
|
||||
|
||||
on_pod = Post.find_by_id(self.id)
|
||||
|
||||
if on_pod && on_pod.diaspora_handle == self.diaspora_handle
|
||||
known_post = user.find_visible_post_by_id(self.id)
|
||||
if known_post
|
||||
local_post = Post.where(:guid => self.guid).first
|
||||
if local_post && local_post.author_id == self.author_id
|
||||
known_post = user.visible_posts(:guid => self.guid).first
|
||||
if known_post
|
||||
if known_post.mutable?
|
||||
known_post.update_attributes(self.to_mongo)
|
||||
known_post.update_attributes(self.attributes)
|
||||
else
|
||||
Rails.logger.info("event=receive payload_type=#{self.class} update=true status=abort sender=#{self.diaspora_handle} reason=immutable existing_post=#{known_post.id}")
|
||||
end
|
||||
elsif on_pod == self
|
||||
user.update_user_refs_and_add_to_aspects(on_pod)
|
||||
Rails.logger.info("event=receive payload_type=#{self.class} update=true status=complete sender=#{self.diaspora_handle} existing_post=#{on_pod.id}")
|
||||
self
|
||||
else
|
||||
user.add_post_to_aspects(local_post)
|
||||
user.notify_if_mentioned(local_post)
|
||||
Rails.logger.info("event=receive payload_type=#{self.class} update=true status=complete sender=#{self.diaspora_handle} existing_post=#{local_post.id}")
|
||||
return local_post
|
||||
end
|
||||
elsif !on_pod
|
||||
user.update_user_refs_and_add_to_aspects(self)
|
||||
elsif !local_post
|
||||
self.save
|
||||
user.add_post_to_aspects(self)
|
||||
user.notify_if_mentioned(self)
|
||||
Rails.logger.info("event=receive payload_type=#{self.class} update=false status=complete sender=#{self.diaspora_handle}")
|
||||
self
|
||||
return self
|
||||
else
|
||||
Rails.logger.info("event=receive payload_type=#{self.class} update=true status=abort sender=#{self.diaspora_handle} reason='update not from post owner' existing_post=#{self.id}")
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
def destroy_comments
|
||||
comments.each{|c| c.destroy}
|
||||
end
|
||||
|
||||
def propogate_retraction
|
||||
self.person.owner.retract(self)
|
||||
self.author.owner.retract(self) if self.author.owner
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
15
app/models/post_visibility.rb
Normal file
15
app/models/post_visibility.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
# Copyright (c) 2010, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class PostVisibility < ActiveRecord::Base
|
||||
|
||||
belongs_to :aspect
|
||||
validates_presence_of :aspect
|
||||
|
||||
belongs_to :post
|
||||
validates_presence_of :post
|
||||
has_one :user, :through => :aspect
|
||||
has_one :person, :through => :post, :foreign_key => :author_id
|
||||
|
||||
end
|
||||
@@ -2,74 +2,62 @@
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class Profile
|
||||
include MongoMapper::EmbeddedDocument
|
||||
class Profile < ActiveRecord::Base
|
||||
require File.join(Rails.root, 'lib/diaspora/webhooks')
|
||||
include Diaspora::Webhooks
|
||||
include ROXML
|
||||
|
||||
xml_reader :diaspora_handle
|
||||
xml_reader :first_name
|
||||
xml_reader :last_name
|
||||
xml_reader :image_url
|
||||
xml_reader :image_url_small
|
||||
xml_reader :image_url_medium
|
||||
xml_reader :birthday
|
||||
xml_reader :gender
|
||||
xml_reader :bio
|
||||
xml_reader :searchable
|
||||
|
||||
key :diaspora_handle, String
|
||||
key :first_name, String
|
||||
key :last_name, String
|
||||
key :image_url, String
|
||||
key :image_url_small, String
|
||||
key :image_url_medium, String
|
||||
key :birthday, Date
|
||||
key :gender, String
|
||||
key :bio, String
|
||||
key :searchable, Boolean, :default => true
|
||||
|
||||
after_validation :strip_names
|
||||
validates_length_of :first_name, :maximum => 32
|
||||
validates_length_of :last_name, :maximum => 32
|
||||
|
||||
xml_attr :diaspora_handle
|
||||
xml_attr :first_name
|
||||
xml_attr :last_name
|
||||
xml_attr :image_url
|
||||
xml_attr :image_url_small
|
||||
xml_attr :image_url_medium
|
||||
xml_attr :birthday
|
||||
xml_attr :gender
|
||||
xml_attr :bio
|
||||
xml_attr :searchable
|
||||
|
||||
before_save :strip_names
|
||||
after_validation :strip_names
|
||||
|
||||
validates_length_of :first_name, :maximum => 32
|
||||
validates_length_of :last_name, :maximum => 32
|
||||
validates_format_of :first_name, :with => /\A[^;]+\z/, :allow_blank => true
|
||||
validates_format_of :last_name, :with => /\A[^;]+\z/, :allow_blank => true
|
||||
|
||||
attr_accessible :first_name, :last_name, :image_url, :image_url_medium,
|
||||
:image_url_small, :birthday, :gender, :bio, :searchable, :date
|
||||
|
||||
def person
|
||||
self._parent_document
|
||||
end
|
||||
belongs_to :person
|
||||
|
||||
def subscribers(user)
|
||||
user.person_objects(user.contacts.where(:pending => false))
|
||||
Person.joins(:contacts).where(:contacts => {:user_id => user.id})
|
||||
end
|
||||
|
||||
def receive(user, person)
|
||||
person.profile = self
|
||||
person.save
|
||||
self
|
||||
Rails.logger.info("event=receive payload_type=profile sender=#{person} to=#{user}")
|
||||
person.profile.update_attributes self.attributes
|
||||
|
||||
person.profile
|
||||
end
|
||||
|
||||
def diaspora_handle
|
||||
#get the parent diaspora handle, unless we want to access a profile without a person
|
||||
(self._parent_document) ? self.person.diaspora_handle : self[:diaspora_handle]
|
||||
(self.person) ? self.person.diaspora_handle : self[:diaspora_handle]
|
||||
end
|
||||
|
||||
def image_url(size = :thumb_large)
|
||||
if size == :thumb_medium
|
||||
self[:image_url_medium]
|
||||
elsif size == :thumb_small
|
||||
self[:image_url_small]
|
||||
else
|
||||
self[:image_url]
|
||||
end
|
||||
result = if size == :thumb_medium && self[:image_url_medium]
|
||||
self[:image_url_medium]
|
||||
elsif size == :thumb_small && self[:image_url_small]
|
||||
self[:image_url_small]
|
||||
else
|
||||
self[:image_url]
|
||||
end
|
||||
result || '/images/user/default.png'
|
||||
end
|
||||
|
||||
|
||||
def image_url= url
|
||||
return image_url if url == ''
|
||||
if url.nil? || url.match(/^https?:\/\//)
|
||||
@@ -103,7 +91,7 @@ class Profile
|
||||
date = Date.new(params['year'].to_i, params['month'].to_i, params['day'].to_i)
|
||||
self.birthday = date
|
||||
elsif [ 'year', 'month', 'day'].all? { |key| params[key].blank? }
|
||||
self.birthday = nil
|
||||
self.birthday = nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -2,108 +2,87 @@
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class Request
|
||||
class Request < ActiveRecord::Base
|
||||
require File.join(Rails.root, 'lib/diaspora/webhooks')
|
||||
|
||||
require File.join(Rails.root, 'lib/postzord/dispatch')
|
||||
include MongoMapper::Document
|
||||
require File.join(Rails.root, 'lib/postzord/dispatch')
|
||||
include Diaspora::Webhooks
|
||||
include ROXML
|
||||
|
||||
xml_reader :sender_handle
|
||||
xml_reader :recipient_handle
|
||||
xml_accessor :sender_handle
|
||||
xml_accessor :recipient_handle
|
||||
|
||||
belongs_to :into, :class => Aspect
|
||||
belongs_to :from, :class => Person
|
||||
belongs_to :to, :class => Person
|
||||
belongs_to :sender, :class_name => 'Person'
|
||||
belongs_to :recipient, :class_name => 'Person'
|
||||
belongs_to :aspect
|
||||
|
||||
validates_presence_of :from, :to
|
||||
validates_uniqueness_of :from_id, :scope => :to_id
|
||||
validates_uniqueness_of :sender_id, :scope => :recipient_id
|
||||
validates_presence_of :sender, :recipient
|
||||
validate :not_already_connected
|
||||
validate :not_friending_yourself
|
||||
|
||||
scope :from, lambda { |person|
|
||||
target = (person.is_a?(User) ? person.person : person)
|
||||
where(:from_id => target.id)
|
||||
}
|
||||
|
||||
scope :to, lambda { |person|
|
||||
target = (person.is_a?(User) ? person.person : person)
|
||||
where(:to_id => target.id)
|
||||
}
|
||||
|
||||
|
||||
def self.instantiate(opts = {})
|
||||
self.new(:from => opts[:from],
|
||||
:to => opts[:to],
|
||||
:into => opts[:into])
|
||||
def self.diaspora_initialize(opts = {})
|
||||
self.new(:sender => opts[:from],
|
||||
:recipient => opts[:to],
|
||||
:aspect => opts[:into])
|
||||
end
|
||||
|
||||
def reverse_for accepting_user
|
||||
Request.new(
|
||||
:from => accepting_user.person,
|
||||
:to => self.from
|
||||
:sender => accepting_user.person,
|
||||
:recipient => self.sender
|
||||
)
|
||||
end
|
||||
|
||||
def sender_handle
|
||||
from.diaspora_handle
|
||||
sender.diaspora_handle
|
||||
end
|
||||
|
||||
def sender_handle= sender_handle
|
||||
self.from = Person.first(:diaspora_handle => sender_handle)
|
||||
self.sender = Person.where(:diaspora_handle => sender_handle).first
|
||||
end
|
||||
|
||||
def recipient_handle
|
||||
to.diaspora_handle
|
||||
recipient.diaspora_handle
|
||||
end
|
||||
|
||||
def recipient_handle= recipient_handle
|
||||
self.to = Person.first(:diaspora_handle => recipient_handle)
|
||||
self.recipient = Person.where(:diaspora_handle => recipient_handle).first
|
||||
end
|
||||
|
||||
def diaspora_handle
|
||||
self.from.diaspora_handle
|
||||
sender_handle
|
||||
end
|
||||
|
||||
def self.hashes_for_person person
|
||||
requests = Request.to(person).all
|
||||
senders = Person.all(:id.in => requests.map{|r| r.from_id}, :fields => [:profile])
|
||||
senders_hash = {}
|
||||
senders.each{|sender| senders_hash[sender.id] = sender}
|
||||
requests.map{|r| {:request => r, :sender => senders_hash[r.from_id]}}
|
||||
end
|
||||
|
||||
|
||||
def notification_type(user, person)
|
||||
if Contact.first(:user_id => user.id, :person_id => person.id)
|
||||
"request_accepted"
|
||||
if Contact.where(:user_id => user.id, :person_id => person.id).first
|
||||
Notifications::RequestAccepted
|
||||
else
|
||||
"new_request"
|
||||
Notifications::NewRequest
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def subscribers(user)
|
||||
[self.to]
|
||||
[self.recipient]
|
||||
end
|
||||
|
||||
def receive(user, person)
|
||||
Rails.logger.info("event=receive payload_type=request sender=#{self.from} to=#{self.to}")
|
||||
Rails.logger.info("event=receive payload_type=request sender=#{self.sender} to=#{self.recipient}")
|
||||
user.receive_contact_request(self)
|
||||
self.save
|
||||
self
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def not_already_connected
|
||||
if Contact.first(:user_id => self.to.owner_id, :person_id => self.from.id)
|
||||
if sender && recipient && Contact.where(:user_id => self.recipient.owner_id, :person_id => self.sender.id).count > 0
|
||||
errors[:base] << 'You have already connected to this person'
|
||||
end
|
||||
end
|
||||
|
||||
def not_friending_yourself
|
||||
if self.to == self.from
|
||||
if self.recipient == self.sender
|
||||
errors[:base] << 'You can not friend yourself'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,7 +6,7 @@ class Retraction
|
||||
include ROXML
|
||||
include Diaspora::Webhooks
|
||||
|
||||
xml_accessor :post_id
|
||||
xml_accessor :post_guid
|
||||
xml_accessor :diaspora_handle
|
||||
xml_accessor :type
|
||||
|
||||
@@ -24,50 +24,40 @@ class Retraction
|
||||
def self.for(object)
|
||||
retraction = self.new
|
||||
if object.is_a? User
|
||||
retraction.post_id = object.person.id
|
||||
retraction.post_guid = object.person.guid
|
||||
retraction.type = object.person.class.to_s
|
||||
else
|
||||
retraction.post_id = object.id
|
||||
retraction.post_guid = object.guid
|
||||
retraction.type = object.class.to_s
|
||||
retraction.object = object
|
||||
end
|
||||
retraction.diaspora_handle = object.diaspora_handle
|
||||
retraction.diaspora_handle = object.diaspora_handle
|
||||
retraction
|
||||
end
|
||||
|
||||
def perform(receiving_user)
|
||||
Rails.logger.debug "Performing retraction for #{post_id}"
|
||||
if self.type.constantize.find_by_id(post_id)
|
||||
unless Post.first(:diaspora_handle => person.diaspora_handle, :id => post_id)
|
||||
Rails.logger.info("event=retraction status=abort reason='no post found authored by retractor' sender=#{person.diaspora_handle} post_id=#{post_id}")
|
||||
return
|
||||
end
|
||||
def target
|
||||
@target ||= self.type.constantize.where(:guid => post_guid).first
|
||||
end
|
||||
|
||||
begin
|
||||
Rails.logger.debug("Retracting #{self.type} id: #{self.post_id}")
|
||||
target = self.type.constantize.first(:id => self.post_id)
|
||||
target.unsocket_from_uid(receiving_user, self) if target.respond_to? :unsocket_from_uid
|
||||
target.delete
|
||||
rescue NameError
|
||||
Rails.logger.info("event=retraction status=abort reason='unknown type'")
|
||||
end
|
||||
end
|
||||
def perform receiving_user
|
||||
Rails.logger.debug "Performing retraction for #{post_guid}"
|
||||
self.target.unsocket_from_user receiving_user if target.respond_to? :unsocket_from_user
|
||||
self.target.destroy
|
||||
target.post_visibilities.delete_all
|
||||
Rails.logger.info("event=retraction status=complete type=#{self.type} guid=#{self.post_guid}")
|
||||
end
|
||||
|
||||
def receive(user, person)
|
||||
if self.type == 'Person'
|
||||
unless self.person.id.to_s == self.post_id.to_s
|
||||
unless self.person.guid.to_s == self.post_guid.to_s
|
||||
Rails.logger.info("event=receive status=abort reason='sender is not the person he is trying to retract' recipient=#{self.diaspora_handle} sender=#{self.person.diaspora_handle} payload_type=#{self.class} retraction_type=person")
|
||||
return
|
||||
end
|
||||
user.disconnected_by(user.visible_person_by_id(self.post_id))
|
||||
user.disconnected_by(self.target)
|
||||
elsif self.target.nil? || self.target.author != self.person
|
||||
Rails.logger.info("event=retraction status=abort reason='no post found authored by retractor' sender=#{person.diaspora_handle} post_guid=#{post_guid}")
|
||||
else
|
||||
self.perform(user)
|
||||
aspects = user.aspects_with_person(self.person)
|
||||
aspects.each do |aspect|
|
||||
aspect.post_ids.delete(self.post_id.to_id)
|
||||
aspect.save
|
||||
end
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
@@ -2,23 +2,15 @@
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class Service
|
||||
include MongoMapper::Document
|
||||
class Service < ActiveRecord::Base
|
||||
include ActionView::Helpers::TextHelper
|
||||
|
||||
belongs_to :user
|
||||
|
||||
key :provider, String
|
||||
key :uid, String
|
||||
key :access_token, String
|
||||
key :access_secret, String
|
||||
key :nickname, String
|
||||
timestamps!
|
||||
belongs_to :user
|
||||
|
||||
def public_message(post, length, url = "")
|
||||
url = "" if post.respond_to?(:photos) && post.photos.count == 0
|
||||
space_for_url = url.blank? ? 0 : (url.length + 1)
|
||||
truncated = truncate(post.message, :length => (length - space_for_url))
|
||||
truncated = truncate(post.message(:plain_text => true), :length => (length - space_for_url))
|
||||
truncated = "#{truncated} #{url}" unless url.blank?
|
||||
return truncated
|
||||
end
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
class Services::Facebook < Service
|
||||
MAX_CHARACTERS = 420
|
||||
|
||||
def provider
|
||||
"facebook"
|
||||
end
|
||||
|
||||
def post(post, url='')
|
||||
Rails.logger.debug("event=post_to_service type=facebook sender_id=#{self.user_id}")
|
||||
message = public_message(post, url)
|
||||
begin
|
||||
RestClient.post("https://graph.facebook.com/me/feed", :message => message, :access_token => self.access_token)
|
||||
RestClient.post("https://graph.facebook.com/me/feed", :message => message, :access_token => self.access_token)
|
||||
rescue Exception => e
|
||||
Rails.logger.info("#{e.message} failed to post to facebook")
|
||||
end
|
||||
@@ -14,4 +18,48 @@ class Services::Facebook < Service
|
||||
def public_message(post, url)
|
||||
super(post, MAX_CHARACTERS, url)
|
||||
end
|
||||
|
||||
def finder(opts = {})
|
||||
Rails.logger.debug("event=friend_finder type=facebook sender_id=#{self.user_id}")
|
||||
response = RestClient.get("https://graph.facebook.com/me/friends", {:params => {:access_token => self.access_token}})
|
||||
data = JSON.parse(response.body)['data']
|
||||
|
||||
data_h = {}
|
||||
data.each do |d|
|
||||
data_h[d['id']] = {:name => d['name']}
|
||||
end
|
||||
|
||||
invitation_objects = Invitation.joins(:recipient).where(:sender_id => self.user_id,
|
||||
:users => {:invitation_service => 'facebook',
|
||||
:invitation_identifier => data_h.keys})
|
||||
|
||||
invitation_objects.each do |inv|
|
||||
data_h[inv.recipient.invitation_identifier][:invitation_id] = inv.id
|
||||
end
|
||||
|
||||
service_objects = Services::Facebook.where(:uid => data_h.keys).includes(:user => {:person => :profile})
|
||||
person_ids_and_uids = {}
|
||||
|
||||
service_objects.each do |s|
|
||||
data_h[s.uid][:person] = s.user.person if s.user.person.profile.searchable
|
||||
person_ids_and_uids[s.user.person.id] = s.uid
|
||||
end
|
||||
|
||||
requests = Request.where(:recipient_id => self.user.person.id, :sender_id => person_ids_and_uids.keys).all
|
||||
requests.each{|r| data_h[person_ids_and_uids[r.sender_id]][:request] = r}
|
||||
|
||||
|
||||
contact_objects = Contact.unscoped.where(:user_id => self.user.id, :person_id => person_ids_and_uids.keys)
|
||||
contact_objects.each{|c| data_h[person_ids_and_uids[c.person_id]][:contact] = c}
|
||||
|
||||
if opts[:local]
|
||||
data_h.delete_if {|key, value| value[:person].nil? }
|
||||
end
|
||||
|
||||
if opts[:remote]
|
||||
data_h.delete_if {|key, value| !value[:person].nil? }
|
||||
end
|
||||
|
||||
data_h
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
class Services::Twitter < Service
|
||||
MAX_CHARACTERS = 140
|
||||
|
||||
def provider
|
||||
"twitter"
|
||||
end
|
||||
|
||||
def post(post, url='')
|
||||
Rails.logger.debug("event=post_to_service type=twitter sender_id=#{self.user_id}")
|
||||
message = public_message(post, url)
|
||||
|
||||
@@ -7,26 +7,124 @@ class StatusMessage < Post
|
||||
include YoutubeTitles
|
||||
require File.join(Rails.root, 'lib/youtube_titles')
|
||||
include ActionView::Helpers::TextHelper
|
||||
|
||||
|
||||
acts_as_taggable_on :tags
|
||||
|
||||
validates_length_of :message, :maximum => 1000, :message => "please make your status messages less than 1000 characters"
|
||||
xml_name :status_message
|
||||
xml_reader :message
|
||||
xml_attr :raw_message
|
||||
|
||||
key :message, String
|
||||
many :photos, :class => Photo, :foreign_key => :status_message_id, :dependent => :destroy
|
||||
has_many :photos, :dependent => :destroy
|
||||
validate :message_or_photos_present?
|
||||
|
||||
attr_accessible :message
|
||||
|
||||
serialize :youtube_titles, Hash
|
||||
before_save do
|
||||
get_youtube_title message
|
||||
end
|
||||
|
||||
before_create :build_tags
|
||||
|
||||
def message(opts = {})
|
||||
self.formatted_message(opts)
|
||||
end
|
||||
|
||||
def raw_message
|
||||
read_attribute(:message)
|
||||
end
|
||||
def raw_message=(text)
|
||||
write_attribute(:message, text)
|
||||
end
|
||||
|
||||
def formatted_message(opts={})
|
||||
return self.raw_message unless self.raw_message
|
||||
|
||||
escaped_message = opts[:plain_text] ? self.raw_message: ERB::Util.h(self.raw_message)
|
||||
mentioned_message = self.format_mentions(escaped_message, opts)
|
||||
self.format_tags(mentioned_message, opts)
|
||||
end
|
||||
|
||||
def format_tags(text, opts={})
|
||||
return text if opts[:plain_text]
|
||||
regex = /(^|\s)#(\w+)/
|
||||
form_message = text.gsub(regex) do |matched_string|
|
||||
"#{$~[1]}<a href=\"/p?tag=#{$~[2]}\" class=\"tag\">##{ERB::Util.h($~[2])}</a>"
|
||||
end
|
||||
form_message
|
||||
end
|
||||
|
||||
def format_mentions(text, opts = {})
|
||||
people = self.mentioned_people
|
||||
regex = /@\{([^;]+); ([^\}]+)\}/
|
||||
form_message = text.gsub(regex) do |matched_string|
|
||||
person = people.detect{ |p|
|
||||
p.diaspora_handle == $~[2] unless p.nil?
|
||||
}
|
||||
|
||||
if opts[:plain_text]
|
||||
person ? ERB::Util.h(person.name) : ERB::Util.h($~[1])
|
||||
else
|
||||
person ? "<a href=\"/people/#{person.id}\" class=\"mention\">@#{ERB::Util.h(person.name)}</a>" : ERB::Util.h($~[1])
|
||||
end
|
||||
end
|
||||
form_message
|
||||
end
|
||||
|
||||
def mentioned_people
|
||||
if self.persisted?
|
||||
create_mentions if self.mentions.empty?
|
||||
self.mentions.includes(:person => :profile).map{ |mention| mention.person }
|
||||
else
|
||||
mentioned_people_from_string
|
||||
end
|
||||
end
|
||||
|
||||
def create_mentions
|
||||
mentioned_people_from_string.each do |person|
|
||||
self.mentions.create(:person => person)
|
||||
end
|
||||
end
|
||||
|
||||
def mentions?(person)
|
||||
mentioned_people.include? person
|
||||
end
|
||||
|
||||
def notify_person(person)
|
||||
self.mentions.where(:person_id => person.id).first.try(:notify_recipient)
|
||||
end
|
||||
|
||||
def mentioned_people_from_string
|
||||
regex = /@\{([^;]+); ([^\}]+)\}/
|
||||
identifiers = self.raw_message.scan(regex).map do |match|
|
||||
match.last
|
||||
end
|
||||
identifiers.empty? ? [] : Person.where(:diaspora_handle => identifiers)
|
||||
end
|
||||
|
||||
def build_tags
|
||||
self.tag_list = tag_strings
|
||||
end
|
||||
|
||||
def tag_strings
|
||||
regex = /(?:^|\s)#(\w+)/
|
||||
matches = self.raw_message.scan(regex).map do |match|
|
||||
match.last
|
||||
end
|
||||
unique_matches = matches.inject(Hash.new) do |h,element|
|
||||
h[element.downcase] = element unless h[element.downcase]
|
||||
h
|
||||
end
|
||||
unique_matches.values
|
||||
end
|
||||
|
||||
def to_activity
|
||||
<<-XML
|
||||
<entry>
|
||||
<title>#{x(self.message)}</title>
|
||||
<link rel="alternate" type="text/html" href="#{person.url}status_messages/#{self.id}"/>
|
||||
<id>#{person.url}status_messages/#{self.id}</id>
|
||||
<title>#{x(self.formatted_message(:plain_text => true))}</title>
|
||||
<content>#{x(self.formatted_message(:plain_text => true))}</content>
|
||||
<link rel="alternate" type="text/html" href="#{self.author.url}p/#{self.id}"/>
|
||||
<id>#{self.author.url}posts/#{self.id}</id>
|
||||
<published>#{self.created_at.xmlschema}</published>
|
||||
<updated>#{self.updated_at.xmlschema}</updated>
|
||||
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||
@@ -35,21 +133,12 @@ class StatusMessage < Post
|
||||
XML
|
||||
end
|
||||
|
||||
|
||||
def public_message(length, url = "")
|
||||
space_for_url = url.blank? ? 0 : (url.length + 1)
|
||||
truncated = truncate(self.message, :length => (length - space_for_url))
|
||||
truncated = "#{truncated} #{url}" unless url.blank?
|
||||
return truncated
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def message_or_photos_present?
|
||||
if self.message.blank? && self.photos.count == 0
|
||||
if self.message.blank? && self.photos == []
|
||||
errors[:base] << 'Status message requires a message or at least one photo'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -7,31 +7,14 @@ require File.join(Rails.root, 'lib/salmon/salmon')
|
||||
require File.join(Rails.root, 'lib/postzord/dispatch')
|
||||
require 'rest-client'
|
||||
|
||||
class User
|
||||
include MongoMapper::Document
|
||||
class User < ActiveRecord::Base
|
||||
include Diaspora::UserModules
|
||||
include Encryptor::Private
|
||||
|
||||
plugin MongoMapper::Devise
|
||||
|
||||
devise :invitable, :database_authenticatable, :registerable,
|
||||
:recoverable, :rememberable, :trackable, :validatable,
|
||||
:timeoutable
|
||||
|
||||
key :username
|
||||
key :serialized_private_key, String
|
||||
key :invites, Integer, :default => 5
|
||||
key :invitation_token, String
|
||||
key :invitation_sent_at, DateTime
|
||||
key :visible_post_ids, Array, :typecast => 'ObjectId'
|
||||
key :visible_person_ids, Array, :typecast => 'ObjectId'
|
||||
|
||||
key :getting_started, Boolean, :default => true
|
||||
key :disable_mail, Boolean, :default => false
|
||||
|
||||
key :email, String
|
||||
key :language, String
|
||||
|
||||
before_validation :strip_and_downcase_username, :on => :create
|
||||
before_validation :set_current_language, :on => :create
|
||||
|
||||
@@ -44,25 +27,45 @@ class User
|
||||
validates_presence_of :person, :unless => proc {|user| user.invitation_token.present?}
|
||||
validates_associated :person
|
||||
|
||||
one :person, :class => Person, :foreign_key => :owner_id
|
||||
has_one :person, :foreign_key => :owner_id
|
||||
delegate :public_key, :posts, :owns?, :diaspora_handle, :name, :public_url, :profile, :first_name, :last_name, :to => :person
|
||||
|
||||
many :invitations_from_me, :class => Invitation, :foreign_key => :from_id
|
||||
many :invitations_to_me, :class => Invitation, :foreign_key => :to_id
|
||||
many :contacts, :class => Contact, :foreign_key => :user_id
|
||||
many :visible_people, :in => :visible_person_ids, :class => Person # One of these needs to go
|
||||
many :raw_visible_posts, :in => :visible_post_ids, :class => Post
|
||||
many :aspects, :class => Aspect, :dependent => :destroy
|
||||
has_many :invitations_from_me, :class_name => 'Invitation', :foreign_key => :sender_id
|
||||
has_many :invitations_to_me, :class_name => 'Invitation', :foreign_key => :recipient_id
|
||||
has_many :aspects
|
||||
has_many :aspect_memberships, :through => :aspects
|
||||
has_many :contacts
|
||||
has_many :contact_people, :through => :contacts, :source => :person
|
||||
has_many :services
|
||||
has_many :user_preferences
|
||||
|
||||
many :services, :class => Service
|
||||
timestamps!
|
||||
|
||||
before_destroy :disconnect_everyone, :remove_person
|
||||
before_destroy :disconnect_everyone, :remove_mentions, :remove_person
|
||||
before_save do
|
||||
person.save if person
|
||||
person.save if person && person.changed?
|
||||
end
|
||||
|
||||
attr_accessible :getting_started, :password, :password_confirmation, :language, :disable_mail
|
||||
|
||||
def update_user_preferences(pref_hash)
|
||||
if self.disable_mail
|
||||
mails = ['mentioned', 'request_received', 'comment_on_post', 'request_acceptance', 'also_commented', 'private_message']
|
||||
mails.each{|x| self.user_preferences.find_or_create_by_email_type(x)}
|
||||
self.disable_mail = false
|
||||
self.save
|
||||
end
|
||||
|
||||
pref_hash.keys.each do |key|
|
||||
if pref_hash[key] == 'true'
|
||||
self.user_preferences.find_or_create_by_email_type(key)
|
||||
else
|
||||
block = self.user_preferences.where(:email_type => key).first
|
||||
if block
|
||||
block.destroy
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def strip_and_downcase_username
|
||||
if username.present?
|
||||
username.strip!
|
||||
@@ -79,65 +82,37 @@ class User
|
||||
if conditions[:username] =~ /^([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})$/i # email regex
|
||||
conditions[:email] = conditions.delete(:username)
|
||||
end
|
||||
super
|
||||
end
|
||||
|
||||
######## Making things work ########
|
||||
|
||||
def method_missing(method, *args)
|
||||
self.person.send(method, *args) if self.person
|
||||
super(conditions)
|
||||
end
|
||||
|
||||
######### Aspects ######################
|
||||
def drop_aspect(aspect)
|
||||
if aspect.contacts.count == 0
|
||||
aspect.destroy
|
||||
else
|
||||
raise "Aspect not empty"
|
||||
end
|
||||
end
|
||||
|
||||
def move_contact(person, to_aspect, from_aspect)
|
||||
return true if to_aspect == from_aspect
|
||||
contact = contact_for(person)
|
||||
if to_aspect == from_aspect
|
||||
true
|
||||
elsif add_contact_to_aspect(contact, to_aspect)
|
||||
delete_person_from_aspect(person.id, from_aspect.id)
|
||||
if add_contact_to_aspect(contact, to_aspect)
|
||||
membership = contact ? contact.aspect_memberships.where(:aspect_id => from_aspect.id).first : nil
|
||||
return ( membership && membership.destroy )
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def salmon(post)
|
||||
created_salmon = Salmon::SalmonSlap.create(self, post.to_diaspora_xml)
|
||||
created_salmon
|
||||
end
|
||||
|
||||
def add_contact_to_aspect(contact, aspect)
|
||||
return true if contact.aspect_ids.include?(aspect.id)
|
||||
contact.aspects << aspect
|
||||
contact.save!
|
||||
end
|
||||
|
||||
def delete_person_from_aspect(person_id, aspect_id, opts = {})
|
||||
aspect = Aspect.find(aspect_id)
|
||||
raise "Can not delete a person from an aspect you do not own" unless aspect.user == self
|
||||
contact = contact_for Person.find(person_id)
|
||||
|
||||
if opts[:force] || contact.aspect_ids.count > 1
|
||||
contact.aspect_ids.delete aspect.id
|
||||
contact.save!
|
||||
aspect.save!
|
||||
else
|
||||
raise "Can not delete a person from last aspect"
|
||||
end
|
||||
return true if contact.aspect_memberships.where(:aspect_id => aspect.id).count > 0
|
||||
contact.aspect_memberships.create!(:aspect => aspect)
|
||||
end
|
||||
|
||||
######## Posting ########
|
||||
def build_post(class_name, opts = {})
|
||||
opts[:person] = self.person
|
||||
opts[:diaspora_handle] = opts[:person].diaspora_handle
|
||||
opts[:author] = self.person
|
||||
opts[:diaspora_handle] = opts[:author].diaspora_handle
|
||||
|
||||
model_class = class_name.to_s.camelize.constantize
|
||||
model_class.instantiate(opts)
|
||||
model_class.diaspora_initialize(opts)
|
||||
end
|
||||
|
||||
def dispatch_post(post, opts = {})
|
||||
@@ -152,24 +127,24 @@ class User
|
||||
end
|
||||
end
|
||||
|
||||
def update_user_refs_and_add_to_aspects(post)
|
||||
Rails.logger.debug("Saving post: #{post}")
|
||||
post.user_refs += 1
|
||||
post.save
|
||||
aspects_to_insert = self.aspects_with_person(post.person)
|
||||
self.add_to_streams(post, aspects_to_insert)
|
||||
def notify_if_mentioned(post)
|
||||
return unless self.contact_for(post.author) && post.respond_to?(:mentions?)
|
||||
|
||||
post.notify_person(self.person) if post.mentions? self.person
|
||||
end
|
||||
|
||||
def add_post_to_aspects(post)
|
||||
return unless self.contact_for(post.author)
|
||||
|
||||
Rails.logger.debug("event=add_post_to_aspects user_id=#{self.id} post_id=#{post.id}")
|
||||
add_to_streams(post, self.aspects_with_person(post.author))
|
||||
post
|
||||
end
|
||||
|
||||
|
||||
def add_to_streams(post, aspects_to_insert)
|
||||
self.raw_visible_posts << post
|
||||
self.save
|
||||
|
||||
post.socket_to_uid(self, :aspect_ids => aspects_to_insert.map{|x| x.id}) if post.respond_to? :socket_to_uid
|
||||
post.socket_to_user(self, :aspect_ids => aspects_to_insert.map{|x| x.id}) if post.respond_to? :socket_to_user
|
||||
aspects_to_insert.each do |aspect|
|
||||
aspect.posts << post
|
||||
aspect.save
|
||||
end
|
||||
end
|
||||
|
||||
@@ -177,64 +152,58 @@ class User
|
||||
if aspect_ids == "all" || aspect_ids == :all
|
||||
self.aspects
|
||||
else
|
||||
if aspect_ids.respond_to? :to_id
|
||||
aspect_ids = [aspect_ids]
|
||||
end
|
||||
aspect_ids.map!{ |x| x.to_id }
|
||||
aspects.all(:id.in => aspect_ids)
|
||||
aspects.where(:id => aspect_ids)
|
||||
end
|
||||
end
|
||||
|
||||
def salmon(post)
|
||||
Salmon::SalmonSlap.create(self, post.to_diaspora_xml)
|
||||
end
|
||||
|
||||
######## Commenting ########
|
||||
def build_comment(text, options = {})
|
||||
comment = Comment.new(:person_id => self.person.id,
|
||||
:diaspora_handle => self.person.diaspora_handle,
|
||||
comment = Comment.new(:author_id => self.person.id,
|
||||
:text => text,
|
||||
:post => options[:on])
|
||||
|
||||
comment.set_guid
|
||||
#sign comment as commenter
|
||||
comment.creator_signature = comment.sign_with_key(self.encryption_key)
|
||||
comment.author_signature = comment.sign_with_key(self.encryption_key)
|
||||
|
||||
if !comment.post_id.blank? && owns?(comment.post)
|
||||
if !comment.post_id.blank? && person.owns?(comment.parent)
|
||||
#sign comment as post owner
|
||||
comment.post_creator_signature = comment.sign_with_key(self.encryption_key)
|
||||
comment.parent_author_signature = comment.sign_with_key(self.encryption_key)
|
||||
end
|
||||
|
||||
comment
|
||||
end
|
||||
|
||||
def dispatch_comment(comment)
|
||||
mailman = Postzord::Dispatch.new(self, comment)
|
||||
mailman.post
|
||||
end
|
||||
|
||||
######### Mailer #######################
|
||||
def mail(job, *args)
|
||||
unless self.disable_mail
|
||||
pref = job.to_s.gsub('Job::Mail', '').underscore
|
||||
unless self.disable_mail || self.user_preferences.exists?(:email_type => pref)
|
||||
Resque.enqueue(job, *args)
|
||||
end
|
||||
end
|
||||
|
||||
######### Posts and Such ###############
|
||||
def retract(post)
|
||||
aspect_ids = aspects_with_post(post.id)
|
||||
aspect_ids.map! { |aspect| aspect.id.to_s }
|
||||
aspects = post.aspects
|
||||
|
||||
retraction = Retraction.for(post)
|
||||
post.unsocket_from_uid(self, retraction, :aspect_ids => aspect_ids) if post.respond_to? :unsocket_from_uid
|
||||
post.unsocket_from_user(self, :aspect_ids => aspects.map { |a| a.id.to_s }) if post.respond_to? :unsocket_from_user
|
||||
mailman = Postzord::Dispatch.new(self, retraction)
|
||||
mailman.post
|
||||
mailman.post
|
||||
|
||||
retraction
|
||||
end
|
||||
|
||||
########### Profile ######################
|
||||
def update_profile(params)
|
||||
if params[:photo]
|
||||
params[:photo].update_attributes(:pending => false) if params[:photo].pending
|
||||
params[:image_url] = params[:photo].url(:thumb_large)
|
||||
params[:image_url_medium] = params[:photo].url(:thumb_medium)
|
||||
params[:image_url_small] = params[:photo].url(:thumb_small)
|
||||
if photo = params.delete(:photo)
|
||||
photo.update_attributes(:pending => false) if photo.pending
|
||||
params[:image_url] = photo.url(:thumb_large)
|
||||
params[:image_url_medium] = photo.url(:thumb_medium)
|
||||
params[:image_url_small] = photo.url(:thumb_small)
|
||||
end
|
||||
if self.person.profile.update_attributes(params)
|
||||
Postzord::Dispatch.new(self, profile).post
|
||||
@@ -245,12 +214,13 @@ class User
|
||||
end
|
||||
|
||||
###Invitations############
|
||||
def invite_user(email, aspect_id, invite_message = "")
|
||||
aspect_object = Aspect.first(:user_id => self.id, :id => aspect_id)
|
||||
if aspect_object
|
||||
Invitation.invite(:email => email,
|
||||
def invite_user(aspect_id, service, identifier, invite_message = "")
|
||||
aspect = aspects.find(aspect_id)
|
||||
if aspect
|
||||
Invitation.invite(:service => service,
|
||||
:identifier => identifier,
|
||||
:from => self,
|
||||
:into => aspect_object,
|
||||
:into => aspect,
|
||||
:message => invite_message)
|
||||
else
|
||||
false
|
||||
@@ -258,46 +228,56 @@ class User
|
||||
end
|
||||
|
||||
def accept_invitation!(opts = {})
|
||||
if self.invited?
|
||||
log_string = "event=invitation_accepted username=#{opts[:username]} "
|
||||
log_string << "inviter=#{invitations_to_me.first.from.diaspora_handle}" if invitations_to_me.first
|
||||
Rails.logger.info log_string
|
||||
self.setup(opts)
|
||||
self.invitation_token = nil
|
||||
self.password = opts[:password]
|
||||
self.password_confirmation = opts[:password_confirmation]
|
||||
self.save!
|
||||
invitations_to_me.each{|invitation| invitation.to_request!}
|
||||
log_string = "event=invitation_accepted username=#{opts[:username]} uid=#{self.id} "
|
||||
log_string << "inviter=#{invitations_to_me.first.sender.diaspora_handle} " if invitations_to_me.first
|
||||
begin
|
||||
if self.invited?
|
||||
self.setup(opts)
|
||||
self.invitation_token = nil
|
||||
self.password = opts[:password]
|
||||
self.password_confirmation = opts[:password_confirmation]
|
||||
self.save!
|
||||
invitations_to_me.each{|invitation| invitation.to_request!}
|
||||
log_string << "success"
|
||||
Rails.logger.info log_string
|
||||
|
||||
self.reload # Because to_request adds a request and saves elsewhere
|
||||
self
|
||||
self.reload # Because to_request adds a request and saves elsewhere
|
||||
self
|
||||
end
|
||||
rescue Exception => e
|
||||
log_string << "failure"
|
||||
Rails.logger.info log_string
|
||||
raise e
|
||||
end
|
||||
end
|
||||
|
||||
###Helpers############
|
||||
def self.build(opts = {})
|
||||
u = User.new(opts)
|
||||
u.email = opts[:email]
|
||||
u.setup(opts)
|
||||
u
|
||||
end
|
||||
|
||||
def setup(opts)
|
||||
self.username = opts[:username]
|
||||
self.email = opts[:email]
|
||||
self.valid?
|
||||
errors = self.errors
|
||||
errors.delete :person
|
||||
return if errors.size > 0
|
||||
|
||||
opts[:person] ||= {}
|
||||
opts[:person][:profile] ||= Profile.new
|
||||
unless opts[:person][:profile].is_a?(Profile)
|
||||
opts[:person][:profile] ||= Profile.new
|
||||
opts[:person][:profile] = Profile.new(opts[:person][:profile])
|
||||
end
|
||||
|
||||
self.person = Person.new(opts[:person])
|
||||
self.person.diaspora_handle = "#{opts[:username]}@#{AppConfig[:pod_uri].host}"
|
||||
self.person.url = AppConfig[:pod_url]
|
||||
|
||||
|
||||
self.serialized_private_key ||= User.generate_key
|
||||
self.serialized_private_key = User.generate_key if self.serialized_private_key.blank?
|
||||
self.person.serialized_public_key = OpenSSL::PKey::RSA.new(self.serialized_private_key).public_key
|
||||
|
||||
self
|
||||
@@ -324,12 +304,21 @@ class User
|
||||
end
|
||||
|
||||
def disconnect_everyone
|
||||
contacts.each { |contact|
|
||||
if contact.person.owner?
|
||||
Contact.unscoped.where(:user_id => self.id).each { |contact|
|
||||
if contact.person.owner_id
|
||||
contact.person.owner.disconnected_by self.person
|
||||
remove_contact(contact)
|
||||
else
|
||||
self.disconnect contact
|
||||
end
|
||||
}
|
||||
self.aspects.delete_all
|
||||
end
|
||||
|
||||
def remove_mentions
|
||||
Mention.where( :person_id => self.person.id).each do |mentioned_person|
|
||||
mentioned_person.delete
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
21
app/models/user_preference.rb
Normal file
21
app/models/user_preference.rb
Normal file
@@ -0,0 +1,21 @@
|
||||
class UserPreference < ActiveRecord::Base
|
||||
belongs_to :user
|
||||
|
||||
validate :must_be_valid_email_type
|
||||
|
||||
|
||||
def must_be_valid_email_type
|
||||
unless valid_email_types.include?(self.email_type)
|
||||
errors.add(:email_type, 'supplied mail type is not a valid or known email type')
|
||||
end
|
||||
end
|
||||
|
||||
def valid_email_types
|
||||
["mentioned",
|
||||
"comment_on_post",
|
||||
"private_message",
|
||||
"request_acceptence",
|
||||
"request_received",
|
||||
"also_commented"]
|
||||
end
|
||||
end
|
||||
@@ -5,8 +5,6 @@
|
||||
class ImageUploader < CarrierWave::Uploader::Base
|
||||
include CarrierWave::MiniMagick
|
||||
|
||||
|
||||
|
||||
def store_dir
|
||||
"uploads/images"
|
||||
end
|
||||
@@ -19,8 +17,6 @@ class ImageUploader < CarrierWave::Uploader::Base
|
||||
model.random_string + model.id.to_s + File.extname(@filename) if @filename
|
||||
end
|
||||
|
||||
|
||||
|
||||
version :thumb_small do
|
||||
process :resize_to_fill => [50,50]
|
||||
end
|
||||
|
||||
41
app/views/admins/user_search.html.haml
Normal file
41
app/views/admins/user_search.html.haml
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
%h3
|
||||
= form_tag 'admin_inviter', :method => :get do
|
||||
email to invite:
|
||||
= text_field_tag 'identifier'
|
||||
= submit_tag 'invite'
|
||||
|
||||
|
||||
|
||||
%h3
|
||||
user search
|
||||
= form_tag 'user_search', :method => :get do
|
||||
username:
|
||||
= text_field_tag 'user[username]', params[:user][:username]
|
||||
|
||||
email:
|
||||
= text_field_tag 'user[email]', params[:user][:email]
|
||||
|
||||
invitation identifier
|
||||
= text_field_tag 'user[invitation_identifier]', params[:user][:invitation_identifier]
|
||||
|
||||
invitation token:
|
||||
= text_field_tag 'user[invitation_token]', params[:user][:invitation_token]
|
||||
= submit_tag 'go'
|
||||
|
||||
|
||||
= "#{@users.count} users found"
|
||||
%br
|
||||
%br
|
||||
= for user in @users
|
||||
= user.inspect
|
||||
%br
|
||||
- if user.person
|
||||
= user.person.inspect
|
||||
%br
|
||||
- if user.person.profile
|
||||
= user.person.profile.inspect
|
||||
%br
|
||||
= "invite token: #{accept_invitation_url(user, :invitation_token => user.invitation_token)}" if user.invitation_token
|
||||
%br
|
||||
%br
|
||||
@@ -3,5 +3,5 @@
|
||||
-# the COPYRIGHT file.
|
||||
|
||||
|
||||
= add_to_aspect_button(aspect_id,person_id)
|
||||
= aspect_membership_button(aspect, contact, person)
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
-# the COPYRIGHT file.
|
||||
|
||||
|
||||
= add_to_aspect_button(@aspect_id,@person_id)
|
||||
= aspect_membership_button(aspect, person, contact)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
%li{:data=>{:guid=>aspect.id}, :class => ("dull" if contacts.length == 0)}
|
||||
%li{:data=>{:guid=>aspect.id}, :class => ("dull" if contacts.size == 0)}
|
||||
.right
|
||||
%b
|
||||
= link_to t('contacts', :count => contact_count), edit_aspect_path(aspect), :rel => 'facebox'
|
||||
= link_to t('contacts', :count => contacts.size), edit_aspect_path(aspect), :rel => 'facebox'
|
||||
%b
|
||||
= aspect.name
|
||||
= link_to aspect.name, edit_aspect_path(aspect), :rel => 'facebox', :class => 'name'
|
||||
%br
|
||||
|
||||
- if contacts.length > 0
|
||||
.contacts
|
||||
- for hash in contacts
|
||||
= person_image_link(hash[:person])
|
||||
- for contact in contacts[0..15]
|
||||
= person_image_link(contact.person)
|
||||
|
||||
9
app/views/aspects/_aspect_list_item.haml
Normal file
9
app/views/aspects/_aspect_list_item.haml
Normal file
@@ -0,0 +1,9 @@
|
||||
-# Copyright (c) 2010, Diaspora Inc. This file is
|
||||
-# licensed under the Affero General Public License version 3 or later. See
|
||||
-# the COPYRIGHT file.
|
||||
|
||||
%li{:data=>{:guid=>aspect.id}}
|
||||
%span.name
|
||||
= link_to aspect.name, aspect
|
||||
.right
|
||||
= aspect_membership_button(aspect, contact, person)
|
||||
@@ -2,17 +2,14 @@
|
||||
-# licensed under the Affero General Public License version 3 or later. See
|
||||
-# the COPYRIGHT file.
|
||||
|
||||
= hidden_field_tag :contact_json, @selected_contacts.map{|contact| contact.person}.to_json
|
||||
|
||||
%h4
|
||||
.right
|
||||
= link_to t('contacts', :count => @contacts.count), aspects_manage_path, :title => t('aspects.manage.manage_aspects')
|
||||
= link_to t('contacts', :count => @contact_count), aspects_manage_path, :title => t('aspects.manage.manage_aspects')
|
||||
|
||||
= @aspect_hashes.count
|
||||
- if @aspect_hashes.count == 1
|
||||
= t('_aspect')
|
||||
- else
|
||||
= t('_aspects')
|
||||
= t('aspects', :count => aspects.count)
|
||||
|
||||
%ul
|
||||
- for a_hash in aspect_hashes
|
||||
= render :partial => 'aspects/aspect', :locals => a_hash
|
||||
- for aspect in aspects
|
||||
= render 'aspects/aspect', :aspect => aspect, :contacts => aspect.contacts.reject{|x| x.pending == true}
|
||||
|
||||
@@ -4,6 +4,13 @@
|
||||
|
||||
|
||||
= render 'shared/publisher', :aspect => aspect, :aspect_ids => aspect_ids
|
||||
#sort_by
|
||||
= t('.sort_by')
|
||||
= link_to_if(session[:sort_order] == 'created_at', t('.activity'), aspects_path(:a_ids => params[:a_ids], :sort_order => 'updated_at'))
|
||||
|
|
||||
= link_to_if(session[:sort_order] == 'updated_at', t('.post_time'), aspects_path(:a_ids => params[:a_ids], :sort_order => 'created_at' ))
|
||||
#main_stream.stream{:data => {:guids => aspect_ids.join(',')}}
|
||||
= render 'shared/stream', :posts => post_hashes
|
||||
= will_paginate @posts
|
||||
= render 'shared/stream', :posts => fakes
|
||||
%a.paginate
|
||||
= t("more")
|
||||
= will_paginate posts
|
||||
|
||||
@@ -8,13 +8,18 @@
|
||||
#edit_aspect_pane
|
||||
- if @contacts.count > 0
|
||||
%h4= t('aspects.edit.add_existing')
|
||||
= render 'shared/contact_list', :aspect_id => aspect.id, :contact_hashes => contacts, :manage => defined?(manage)
|
||||
= render 'shared/contact_list', :aspect_id => aspect.id, :contacts => contacts, :manage => defined?(manage)
|
||||
|
||||
= render 'shared/add_contact', :aspect_id => aspect.id
|
||||
|
||||
%hr
|
||||
= form_for aspect do |asp|
|
||||
= asp.text_field :name, :value => aspect.name
|
||||
= t('aspects.contacts_visible')
|
||||
= aspect.check_box :contacts_visible, :default => true
|
||||
%br
|
||||
= t('aspects.contacts_not_visible')
|
||||
-#contacts_visible should be editable here
|
||||
= asp.submit t('aspects.edit.rename_aspect')
|
||||
|
||||
%hr
|
||||
|
||||
@@ -12,5 +12,12 @@
|
||||
%p
|
||||
= aspect.label :name , t('.name')
|
||||
= aspect.text_field :name, :maxlength => 20
|
||||
|
||||
%p.checkbox_select
|
||||
= aspect.label :contacts_visible, t('aspects.edit.make_aspect_list_visible')
|
||||
= aspect.check_box :contacts_visible, :default => true
|
||||
|
||||
%br
|
||||
|
||||
= aspect.submit t('.create'), :class => 'button'
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user