196 Commits

Author SHA1 Message Date
tilly-Q
9b8ef022ef In this commit, I have made a few changes and tightened up some of my models
code. I added in two major pieces of functionality: table foundations and a
decorator to confirm whether or not a user is a member of a certain group.

Table Foundations are default rows that should be present in a given table as
soon as the database is initialized. For example, I am using these to populate
the core__groups table with all of the necessary groups ('moderator', 'com-
menter', etc). Right now, this is achieved by adding a dictionary of parameters
(with the parameters as lists) to the constant FOUNDATIONS in
mediagoblin.db.models. The keys to this dictionary are uninstantiated classes.
The classes which require foundations also have must have a constructor so that
the list of parameters can be passed appropriately like so:
        Model(*parameters)
In order to implement these foundations, I added the method populate_table_fou-
-ndations to MigrationManager in mediagoblin.db.migration_tools.

The decorator, called user_in_group, accepts as a parameter a unicode string,
and then decides whether to redirect to 403 or let the user access the page. The
identifier is the Group.group_name string, because I believe that will allow for
the most readable code.

I also added in the simple decorator require_admin_login.

In terms of tightening up my code, I made many minor changes to my use of white
space and made a few small documentation additions. I removed a vestigial class
(ReportForm) from mediagoblin.user_pages.forms. I moved all of my migrations in-
to one registered Migration.

Setting up Foundations
==============================

--\ mediagoblin/db/migration_tools.py
--| created: MigrationManager.populate_table_foundations
--| modified: MigrationManager.init_or_migrate to run
  |     self.populate_table_foundations on init

--\ mediagoblin/db/models.py
--| created: FOUNDATIONS
----| created: group_foundations

Working With Permissions
==============================
--\ mediagoblin/decorators.py
--| created: user_in_group
--| created: require_admin_login

--\ mediagoblin/user_pages/views.py
--| modified: added decorator user_in_group to file_a_report

--\ mediagoblin/admin/views.py
--| modified: added decorator require_admin_login to all views functions

General Code Tidying
=============================

--/ mediagoblin/admin/views.py
--/ mediagoblin/user_pages/forms.py
--/ mediagoblin/db/models.py
--/ mediagoblin/user_pages/lib.py
--/ mediagoblin/user_pages/views.py
--/ mediagoblin/db/migrations.py
2013-06-27 14:13:42 -07:00
tilly-Q
30a9fe7c1c This is the first stage of my project of implenting admin/moderator functiona-
lity. At this point, I have finished all the of basic work with the models! I
still need to do some tightening of their documentation, but they seem to be
working well.

Working with Models
========================================

--\ mediagoblin/db/models.py
--| Added in the Report model and table. This model is strictly a parent
----| Added in the CommentReport model which holds information about a report
    | filed against a comment. This class inherits from Report.
----| Added in the MediaReport model which holds information about a report f-
    | -iled against a media entry. This class inherits from Report.
--| Added in a UserBan model and table. This model is in a one to one relatio-
  | -nship with User. This object acts as a marker for whether a user is banned
  | or not.
--| Added in a Group model. These objects are in a many-to-many relationship
  | with User to explain which privileges a User has.
----| Added in GroupUserAssociation which is a table used to hold this many to
    | many relationship  between Group & User.

--\ mediagoblin/db/migrations.py
--| Added in the migrations for all of the additions to models
--| Added UserBan_v0
--| Added Report_v0
----| Added CommentReport_v0
----| Added MediaReport_v0
--| Added Group_v0
----| Added GroupUserAssociation_v0

Working with Templates, Views, and Routing
===============================================

>>> Reporting a Comment or a MediaEntry

--\ mediagoblin/user_pages/views.py
--| Added in the function file_a_report to allow user to file reports against
  | MediaEntries or Comments. Handles GET and POST requests.
--| Added in the function file_a_comment_report which uses file_a_report but
  | also catches appropriate information for comment_ids. I may be able to do
  | this more eloquently with decorators.

--\ mediagoblin/user_pages/routing.py
--| Added in route 'mediagoblin.user_pages.media_home.report_media'
  | (linked to address /u/<user>/m/<media>/report/ )
--| Added in route ''mediagoblin.user_pages.media_home.report_comment'
  | (linked to address /u/<user>/m/<media>/c/<comment>/report/ )

--\ mediagoblin/templates/mediagoblin/user_pages/report.html
--| I created this file to handle the filing of a report.

--\ mediagoblin/templates/mediagoblin/user_pages/media.html
--| Modified this file to add in links allowing users to report either media
  | or comments.

--\ mediagoblin/user_pages/lib.py
--| Added in build_report_form which processes data as either a CommentReport or
  | a MediaReport depending on which parameters are present

--\ mediagoblin/user_pages/forms.py
--| Added in CommentReportForm
--| Added in MediaReportForm
--| note: ReportForm is vestigial to an earlier strategy I used and I'll remove it
  | promptly

--\ mediagoblin/decorators.py
--| Added in 'get_media_comment_by_id' for use in mediagoblin/user_pages/views.py

>>> New Admin Panels

--\ mediagoblin/admin/views.py
--| Added in the function admin_users_panel
--| Added in the function admin_reports_panel

--\ mediagoblin/admin/routing.py
--| Added in route 'mediagoblin.admin.users'
  | (linked to address '/a/users')
--| Added in route 'mediagoblin.admin.reports'
  | (linked to address '/a/reports/')

--\ mediagoblin/templates/admin/user.html
--| Created this file as a template for monitoring users

--\ mediagoblin/templates/admin/report.html
--| Created this file as a template for monitoring reports filed against media or
  | comments
2013-06-24 16:35:31 -07:00
Joar Wandborg
2d7b6bdef9 New notifications
- Added request.notifications
- Email configuration fixes
  - Set config_spec default SMTP port to `0` and switch to SSL/non-SSL
    default if `port == 0`
  - Added email_smtp_use_ssl configuration setting
- Added migrations for notification tables
- Added __repr__ to MediaComment(Mixin)
- Added MediaComment.get_entry => MediaEntry
- Added CommentSubscription, CommentNotification, Notification,
  ProcessingNotification tables
- Added notifications.task to celery init
- Fixed a bug in the video transcoder where pygst would hijack the
  --help argument.
- Added notifications
  - views
    - silence
    - subscribe
  - routes
  - utility methods
  - celery task
- Added half-hearted .active comment CSS style
- Added quick JS to show header_dropdown
- Added fragment template to show notifications in header_dropdown
- Added fragment template to show subscribe/unsubscribe buttons on
  media/comment pages
- Updated celery setup tests with notifications.task
- Tried to fix test_misc tests that I broke
- Added notification tests
- Added and extended tests.tools fixtures
- Integrated new notifications into media_home, media_post_comment views
- Bumped SQLAlchemy dependency to >= 0.8.0 since we need polymorphic for
  the notifications to work
2013-06-09 21:18:37 +02:00
Christopher Allan Webber
94fadafe09 Merge remote-tracking branch 'refs/remotes/dthompson/453_disable_comments' 2013-05-10 16:33:52 -05:00
Elrond
fc45b38626 Use collection.url_for_self more; Add missing /a.
Using collection.url_for_self(request.urlgen) instead
of request.urlgen(lengthy) is so much nicer, so using
it around the place.

Also added a few missing </a> in one template.
2013-05-05 14:29:57 +02:00
Elrond
2e6ee596ad Create redir_obj and use it around.
This is a shortcut function to redirect to the main page
for an object. Objects currently supported: media entries
and collections.

And go around and replace various places to use this.
2013-04-28 23:09:20 +02:00
Elrond
2041ceae1f Fix translations for collections and drop useless try.
Don't do:  _("With some value: %s" % value)
Please do: _("WIth some value: %s") % value

Fixed for collection messages.

Also removed a
  try:
    some_code.
  except Exception as e:
    raise

No point in doing that.

Fixing the indentation of some_code comes in an extra
commit, because changing indentation is annoying enough
alone, so don't mix it with other changes.
2013-04-27 15:08:07 +02:00
Christopher Allan Webber
a789b713f5 Switching non-forms back to using normal pass_to_ugettext 2013-04-24 16:40:30 -05:00
Aditi Mittal
665b9c420a Fix-bug-667-Use-lazy_pass_to_ugettext-for-forms. 2013-04-24 16:40:29 -05:00
Elrond
6bea8a9094 Create add_media_to_collection()
The ideas is by Alon Levy.

Not only media_collect, but also other places might want to
add media to a collection. So refactor this into a function
for easier usage.
2013-04-23 12:29:17 +02:00
David Thompson
99338b6a64 Do not allow comments to be posted when they are disabled. 2013-04-13 10:42:40 -04:00
Hans Lo
c5d341d79d Use WTForms data field in user_pages/views.py
Missed case in a previous commit.
2013-03-28 04:26:48 -04:00
Hans Lo
2263a4cb5c Use WTForms data field in user_pages/views.py 2013-03-24 13:56:08 -04:00
Elrond
e9330b9552 655: Fix collection fetching for media_collect()
The problem is:

    Collection.query.filter_by(id=X, ...)

1. X = form.collection.data
   This works nicely for the completely empty form (X = None).
   It does not work for a selected collection, because X
   will be the collection, not its id.

2. X = request.form.get('collection') (old code).
   This one works mostly, except for the completely empty
   form on postgres, because in this case X = u"__None" and
   postgres does not like comparing an integer column with
   a string.

Fix:
    collection = form.collection.data
    if collection and collection.creator != request.user.id:
        collection = None
2013-03-10 21:19:16 +01:00
Christopher Allan Webber
e9b69c7d0e Elrond points out that we should use form.collection.data
That's true; I'm not sure what it's fixing, but he thinks it's fixing
something.  Anyway, it's correct :)

This commit sponsored by Philippe Gauthier.  Thanks!
2013-03-04 11:45:14 -06:00
Christopher Allan Webber
17e4679ddc Three fixes to collection adding view, one of them a serious security bug
- Don't let people who aren't the authors of a collection from adding
   things to it (handled by forcing the user check in the query)
 - request url in case invalid collection selected fixed
 - collection_item.author doesn't yet exist; removing the selection
   (we might want multiple people to be able to edit a collection in
   the future but that future does not yet exist; as Elrond said,
   remove this "false hope")

Thanks to Elrond to pointing out these issues.

And thanks to David Kindler for sponsoring this commit!
2013-03-04 10:12:48 -06:00
Elrond
b7a3798e18 Fix some media page redirects in media_collect.
Use .slug_or_id instead of only .id.
2013-03-01 22:08:24 +01:00
Elrond
918d811a78 Fixup _("...") % (...) in media_collect.
Get some messages translated.

Bad:  _("..." % (...))
Good: _("...") % (...)
2013-03-01 22:07:12 +01:00
Elrond
96a2249bc0 Use media.id for collecting media too.
Also remove some useless whitespace while at it.
2013-02-24 16:22:48 +01:00
Christopher Allan Webber
38905733e8 Fixing user gallery tags filter to be on slug rather than name.
This commit sponsored by Kat Walsh.  Thanks, Kat!
2013-02-21 16:13:56 -06:00
Christopher Allan Webber
60a7eb9ca5 Merge remote-tracking branch 'refs/remotes/spaetz/WIP/user_tag_gallery' 2013-02-21 15:55:26 -06:00
Joar Wandborg
61e39d90e5 Fix errors in collection views
When a collection does not exist, render the 404 page.
2013-02-18 14:41:34 +01:00
Joar Wandborg
ab9b0b4175 Change from email format in tag URI to domain format
Also fixed a bug (thanks pyflakes)
2013-02-13 23:12:55 +01:00
Joar Wandborg
19ad2e0cd0 Address concerns in Issue #543
- Fixed PEP-008 issues.
- Removed .user-{user} from the tag URI and put it before the domain,
  such as {user}@{host} instead.
- Use year from collection.created instead of current year.
2013-02-13 22:23:27 +01:00
Sebastian Spaeth
f2c0bf3e34 Implement user's tag filtered gallery page
tags used to be global, you could only browse media by tag for all users.
This patch implements a view that allows us to browse only a user's tagged
media.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2013-01-21 17:27:42 +01:00
Elrond
7d16a01bae Fix linking to comments.
when linking to a comment in a MediaEntry, the page did not
contain a <a name="comment"> because, well:

We fetched a string comment-id from the routing. And the
pagination code tried to compare that to the int id on the
comment.

Fix is to let routing fetch an int from the url. Easy.

Relatedly remove duplicated comment_id fetching from the
URL in the view.
2013-01-17 23:57:40 +01:00
Sebastian Spaeth
ba5ea989a5 Return to media collection page if no collection selected
schendje rightly pointed out that we should not return to the media
homepage if we did not select a collection on the "collect" page, but
should actually return to the collect page.

This is an improvement of the user experience ;-)

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2013-01-17 22:39:22 +01:00
Sebastian Spaeth
8c33fc7505 Merge branch '540_User_delete_deletes_related_entries' 2013-01-17 11:52:22 +01:00
Sebastian Spaeth
fdc34b8ba7 Implement MediaEntry().delete() (#540)
Deleting a MediaEntry instance will automatically
delete all related comments and files/attachments. This moves
implementation logic out of views.py and allows to make use of this
functionality when e.g. deleting a User() account.

Whenever a MediaEntry entry is deleted, this will also sql-delete
the corresponding MediaFile entry.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2013-01-17 11:48:07 +01:00
Christopher Allan Webber
27aebe05a6 Merge remote-tracking branch 'refs/remotes/elrond/misc/use_media_id' 2013-01-16 11:06:22 -06:00
Stefano Zacchiroli
4f8f0353b1 collection browsing: rename view/template user_collections -> collection_list
Rationale, avoid confusion between views user_collection and user_collections
(note trailing "s"). Ditto for the collection(s).html templates.
2013-01-15 23:28:10 +01:00
Stefano Zacchiroli
947f38c0b9 collection browsing: remove pagination support
rationale: we do not expect hundreds of collection (and it was likely broken
anyhow)

thanks to Elrond der Elbenfuerst for pointing this out
2013-01-15 23:04:37 +01:00
Stefano Zacchiroli
b0cc1ade40 collections: add support to browse existing collections
- add a route at /u/<user>/collections/ (note trailing 's') that lists
  all existing collections
- move there the "Create new collection" link, if the user is logged in
- add a new link "Browse collections" from root.html
2013-01-15 21:40:05 +01:00
Elrond
461dd9717c Start to use the media_id in "admin" URLs.
We have a bunch of URLs that are more for internal use. At
least they're definitely not intended to be posted
somewhere for long term useage.

When those things affect a media, it's much better to
reference the media by its id. This can't change, ever.
This is better for races.
Like someone posting a comment while the owner
corrects a typo in the slug.
2013-01-11 21:48:03 +01:00
Sebastian Spaeth
20be9bb77d Remove custom GMQuery class
We provided a custom GMQuery class that offered a .sort() method for
compatibility with the Mongo syntax. Now that we have settled for sqlalchemy
which uses the order_by() method, we can safely remove this custom class
and move a little closer to "pure" and native sqlalchemy usage.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2013-01-07 13:52:37 +01:00
Sebastian Spaeth
b0c8328e54 Move db.sql.models* to db.models* 2013-01-07 11:44:29 +01:00
Sebastian Spaeth
0efe9e2796 Remove mediagoblin.db.sql.fake.DESCENDING
This is the last remnant that requires us to keep db.sql.fake.py. Use
ModelName.desc() or sqlalchemy.sql.expression.desc(column) to achieve
descending sorts.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2013-01-07 11:15:04 +01:00
Sebastian Spaeth
71717fd531 Remove ObjectId from the tree
This was one of the last remaining Mongo holdouts and has been removed from
the tree herewith. Good bye, ObjectId.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-12-25 20:52:25 +01:00
Elrond
b39d1f2351 Mongo removal: Remove the validate=True arg to obj.save()
all callers were forced to use validate=True anyway. So
remove this useless stuff.
2012-12-24 00:07:24 +01:00
Sebastian Spaeth
dfc23dd1e1 Compare user by id not object equality
Elrond correctly remarked that we should be comparing user by id
and not by comparing User objects (as I mistakenly did). He is
right, of course!

Also removing the 2 stray debug prints that were left over.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-12-23 12:12:11 +01:00
Sebastian Spaeth
2fb36dac31 Improve sqlalchemy filter rules
Thanks to Elrond's review. 1) Use filter_by more consistently
rather than mixing filter and filter_by. 2) Add multiple AND
conditions in the same filter rule rather than using separate
ones. 3) The atom feeds used filter_by(Modelname.attr == ...)
which was the wrong pattern, of course.

Thanks for repairing my junk Elrond!

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-12-23 12:08:51 +01:00
Sebastian Spaeth
af008743ca Remove mongolisms from user_pages.view #451 2012-12-21 11:30:29 +01:00
Sebastian Spaeth
f6bc033603 Refactor media_collect
Remove lots of MOngolisms. Refactor this to remove some indentation
levels. Don't do:
 if success:
   ...
   if success:
     ....
     if success:
     ...
2012-12-21 11:29:39 +01:00
Sebastian Spaeth
950124e640 webob.HTTPFound --> MG.tools.redirect
Transition away from webob.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-12-21 08:11:40 +01:00
Sebastian Spaeth
5c2b84869f Move DBModel._id -> DBModel.id
We were refering to model._id in most of the code base as this is
what Mongo uses. However, each use of _id required a) fixup of queries:
e.g. what we did in our find() and find_one() functions moving all
'_id' to 'id'. It also required using AliasFields to make the ._id
attribute available. This all means lots of superfluous fixing and
transitioning in a SQL world.

It will also not work in the long run. Much newer code already refers
to the objects by model.id (e.g. in the oauth plugin), which will break
with Mongo. So let's be honest, rip out the _id mongoism and live with
.id as the one canonical way to address objects.

This commit modifies all users and providers of model._id to use
model.id instead. This patch works with or without Mongo removed first,
but will break Mongo usage (even more than before)

I have not bothered to fixup db.mongo.* and db.sql.convert
(which converts from Mongo to SQL)

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-12-21 00:30:48 +01:00
Sebastian Spaeth
e2ae0f5920 Fix user collection gallery
We were fetching the user collection gallery by slug only, so if two users
had the same collection slug, we would not have been sure which one we'd get.

Fix this by explicitly only fetching the specific user's collections. Also
switch over the view function to make use of the new active_user_from_url
decorator that fetches the User() object for us.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-12-05 13:55:31 +01:00
Sebastian Spaeth
64c2a4002c Switch over the user gallery to the active_user_from_url decorator
This switches the user gallery page over to use the new decorator, and
cleans up the queries to be in proper sqlalchemy format rather than the
old mongo format.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-12-05 13:55:30 +01:00
Sebastian Spaeth
5f8b4ae895 make media_manager a property of MediaEntry in mixin.py
In all cases where get_media_manager(_media_type_as_string) was called in
our code base we ultimately passed in a "MediaEntry().media_type" to get
the matching MEDIA_MANAGER. It so makes sense to make this a function of
the MediaEntry rather than a global function in mediagoblin.media_types and
passing around media_entry.media_type as arguments all the time.

It saves a few import statements and arguments. I also made it so the
Media_manager property is cached for subsequent calls, although I am not too
sure that this is needed (there are other cases for which this would make
more sense)

Also add a get_media_manager test to the media submission tests. It submits
an image and checks that both media.media_type and media.media_manager
return the right thing. Not sure if these tests could not be merged with an
existing submission test, but it can't hurt to have things explicit.

TODO: Right now we iterate through all existing media_managers to find the
right one based on the string of its module name. This should be made a simple
dict lookup to avoid all the extra work.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-12-04 15:15:41 +01:00
Joar Wandborg
111a609df5 Replaced all request.POST with request.form, ...
- Fixed error handling in OAuth plugin
- Changed request.POST file fields to request.files
2012-09-29 21:08:20 +02:00
Joar Wandborg
6d1e55b262 Style fixes 2012-09-18 18:19:26 +02:00