diff options
Diffstat (limited to 'mediagoblin/gmg_commands')
-rw-r--r-- | mediagoblin/gmg_commands/__init__.py | 22 | ||||
-rw-r--r-- | mediagoblin/gmg_commands/addmedia.py | 105 | ||||
-rw-r--r-- | mediagoblin/gmg_commands/assetlink.py | 151 | ||||
-rw-r--r-- | mediagoblin/gmg_commands/dbupdate.py | 52 | ||||
-rw-r--r-- | mediagoblin/gmg_commands/import_export.py | 6 | ||||
-rw-r--r-- | mediagoblin/gmg_commands/reprocess.py | 302 | ||||
-rw-r--r-- | mediagoblin/gmg_commands/theme.py | 122 | ||||
-rw-r--r-- | mediagoblin/gmg_commands/users.py | 36 | ||||
-rw-r--r-- | mediagoblin/gmg_commands/util.py | 2 |
9 files changed, 639 insertions, 159 deletions
diff --git a/mediagoblin/gmg_commands/__init__.py b/mediagoblin/gmg_commands/__init__.py index 6aed4f6c..a1eb599d 100644 --- a/mediagoblin/gmg_commands/__init__.py +++ b/mediagoblin/gmg_commands/__init__.py @@ -41,11 +41,23 @@ SUBCOMMAND_MAP = { 'setup': 'mediagoblin.gmg_commands.dbupdate:dbupdate_parse_setup', 'func': 'mediagoblin.gmg_commands.dbupdate:dbupdate', 'help': 'Set up or update the SQL database'}, - 'theme': { - 'setup': 'mediagoblin.gmg_commands.theme:theme_parser_setup', - 'func': 'mediagoblin.gmg_commands.theme:theme', - 'help': 'Theming commands', - } + 'assetlink': { + 'setup': 'mediagoblin.gmg_commands.assetlink:assetlink_parser_setup', + 'func': 'mediagoblin.gmg_commands.assetlink:assetlink', + 'help': 'Link assets for themes and plugins for static serving'}, + 'reprocess': { + 'setup': 'mediagoblin.gmg_commands.reprocess:reprocess_parser_setup', + 'func': 'mediagoblin.gmg_commands.reprocess:reprocess', + 'help': 'Reprocess media entries'}, + 'addmedia': { + 'setup': 'mediagoblin.gmg_commands.addmedia:parser_setup', + 'func': 'mediagoblin.gmg_commands.addmedia:addmedia', + 'help': 'Reprocess media entries'}, + # 'theme': { + # 'setup': 'mediagoblin.gmg_commands.theme:theme_parser_setup', + # 'func': 'mediagoblin.gmg_commands.theme:theme', + # 'help': 'Theming commands', + # } ## These might be useful, mayyyybe, but don't really work anymore ## due to mongo change and the "versatility" of sql options. diff --git a/mediagoblin/gmg_commands/addmedia.py b/mediagoblin/gmg_commands/addmedia.py new file mode 100644 index 00000000..c33a8c56 --- /dev/null +++ b/mediagoblin/gmg_commands/addmedia.py @@ -0,0 +1,105 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os + +from mediagoblin.gmg_commands import util as commands_util +from mediagoblin.submit.lib import ( + submit_media, get_upload_file_limits, + FileUploadLimit, UserUploadLimit, UserPastUploadLimit) + +from mediagoblin import mg_globals + + +def parser_setup(subparser): + subparser.add_argument( + 'username', + help="Name of user this media entry belongs to") + subparser.add_argument( + 'filename', + help="Local file on filesystem") + subparser.add_argument( + "-d", "--description", + help="Description for this media entry") + subparser.add_argument( + "-t", "--title", + help="Title for this media entry") + subparser.add_argument( + "-l", "--license", + help=( + "License this media entry will be released under. " + "Should be a URL.")) + subparser.add_argument( + "-T", "--tags", + help=( + "Comma separated list of tags for this media entry.")) + subparser.add_argument( + "-s", "--slug", + help=( + "Slug for this media entry. " + "Will be autogenerated if unspecified.")) + + subparser.add_argument( + '--celery', + action='store_true', + help="Don't process eagerly, pass off to celery") + + +def addmedia(args): + # Run eagerly unless explicetly set not to + if not args.celery: + os.environ['CELERY_ALWAYS_EAGER'] = 'true' + + app = commands_util.setup_app(args) + + # get the user + user = app.db.User.query.filter_by(username=args.username.lower()).first() + if user is None: + print "Sorry, no user by username '%s'" % args.username + return + + # check for the file, if it exists... + filename = os.path.split(args.filename)[-1] + abs_filename = os.path.abspath(args.filename) + if not os.path.exists(abs_filename): + print "Can't find a file with filename '%s'" % args.filename + return + + upload_limit, max_file_size = get_upload_file_limits(user) + + def maybe_unicodeify(some_string): + # this is kinda terrible + if some_string is None: + return None + else: + return unicode(some_string) + + try: + submit_media( + mg_app=app, + user=user, + submitted_file=file(abs_filename, 'r'), filename=filename, + title=maybe_unicodeify(args.title), + description=maybe_unicodeify(args.description), + license=maybe_unicodeify(args.license), + tags_string=maybe_unicodeify(args.tags) or u"", + upload_limit=upload_limit, max_file_size=max_file_size) + except FileUploadLimit: + print "This file is larger than the upload limits for this site." + except UserUploadLimit: + print "This file will put this user past their upload limits." + except UserPastUploadLimit: + print "This user is already past their upload limits." diff --git a/mediagoblin/gmg_commands/assetlink.py b/mediagoblin/gmg_commands/assetlink.py new file mode 100644 index 00000000..148ebe9e --- /dev/null +++ b/mediagoblin/gmg_commands/assetlink.py @@ -0,0 +1,151 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os + +from mediagoblin import mg_globals +from mediagoblin.init import setup_global_and_app_config +from mediagoblin.gmg_commands import util as commands_util +from mediagoblin.tools.theme import register_themes +from mediagoblin.tools.translate import pass_to_ugettext as _ +from mediagoblin.tools.common import simple_printer +from mediagoblin.tools import pluginapi + + +def assetlink_parser_setup(subparser): + # theme_subparsers = subparser.add_subparsers( + # dest=u"subcommand", + # help=u'Assetlink options') + + # # Install command + # install_parser = theme_subparsers.add_parser( + # u'install', help=u'Install a theme to this mediagoblin instance') + # install_parser.add_argument( + # u'themefile', help=u'The theme archive to be installed') + + # theme_subparsers.add_parser( + # u'assetlink', + # help=( + # u"Link the currently installed theme's assets " + # u"to the served theme asset directory")) + pass + + +########### +# Utilities +########### + +def link_theme_assets(theme, link_dir, printer=simple_printer): + """ + Returns a list of string of text telling the user what we did + which should be printable. + """ + link_dir = link_dir.rstrip(os.path.sep) + link_parent_dir = os.path.dirname(link_dir) + + if theme is None: + printer(_("Cannot link theme... no theme set\n")) + return + + def _maybe_unlink_link_dir(): + """unlink link directory if it exists""" + if os.path.lexists(link_dir) \ + and os.path.islink(link_dir): + os.unlink(link_dir) + return True + + return + + if theme.get('assets_dir') is None: + printer(_("No asset directory for this theme\n")) + if _maybe_unlink_link_dir(): + printer( + _("However, old link directory symlink found; removed.\n")) + return + + _maybe_unlink_link_dir() + + # make the link directory parent dirs if necessary + if not os.path.lexists(link_parent_dir): + os.makedirs(link_parent_dir) + + os.symlink( + theme['assets_dir'].rstrip(os.path.sep), + link_dir) + printer("Linked the theme's asset directory:\n %s\nto:\n %s\n" % ( + theme['assets_dir'], link_dir)) + + +def link_plugin_assets(plugin_static, plugins_link_dir, printer=simple_printer): + """ + Arguments: + - plugin_static: a mediagoblin.tools.staticdirect.PluginStatic instance + representing the static assets of this plugins' configuration + - plugins_link_dir: Base directory plugins are linked from + """ + # link_dir is the final directory we'll link to, a combination of + # the plugin assetlink directory and plugin_static.name + link_dir = os.path.join( + plugins_link_dir.rstrip(os.path.sep), plugin_static.name) + + # make the link directory parent dirs if necessary + if not os.path.lexists(plugins_link_dir): + os.makedirs(plugins_link_dir) + + # See if the link_dir already exists. + if os.path.lexists(link_dir): + # if this isn't a symlink, there's something wrong... error out. + if not os.path.islink(link_dir): + printer(_('Could not link "%s": %s exists and is not a symlink\n') % ( + plugin_static.name, link_dir)) + return + + # if this is a symlink and the path already exists, skip it. + if os.path.realpath(link_dir) == plugin_static.file_path: + # Is this comment helpful or not? + printer(_('Skipping "%s"; already set up.\n') % ( + plugin_static.name)) + return + + # Otherwise, it's a link that went to something else... unlink it + printer(_('Old link found for "%s"; removing.\n') % ( + plugin_static.name)) + os.unlink(link_dir) + + os.symlink( + plugin_static.file_path.rstrip(os.path.sep), + link_dir) + printer('Linked asset directory for plugin "%s":\n %s\nto:\n %s\n' % ( + plugin_static.name, + plugin_static.file_path.rstrip(os.path.sep), + link_dir)) + + +def assetlink(args): + """ + Link the asset directory of the currently installed theme and plugins + """ + mgoblin_app = commands_util.setup_app(args) + app_config = mg_globals.app_config + + # link theme + link_theme_assets(mgoblin_app.current_theme, app_config['theme_linked_assets_dir']) + + # link plugin assets + ## ... probably for this we need the whole application initialized + for plugin_static in pluginapi.hook_runall("static_setup"): + link_plugin_assets( + plugin_static, app_config['plugin_linked_assets_dir']) diff --git a/mediagoblin/gmg_commands/dbupdate.py b/mediagoblin/gmg_commands/dbupdate.py index 32700c40..05762946 100644 --- a/mediagoblin/gmg_commands/dbupdate.py +++ b/mediagoblin/gmg_commands/dbupdate.py @@ -25,24 +25,26 @@ from mediagoblin.tools.common import import_component _log = logging.getLogger(__name__) logging.basicConfig() -_log.setLevel(logging.DEBUG) +## Let's not set the level as debug by default to avoid confusing users :) +# _log.setLevel(logging.DEBUG) def dbupdate_parse_setup(subparser): pass class DatabaseData(object): - def __init__(self, name, models, migrations): + def __init__(self, name, models, foundations, migrations): self.name = name self.models = models + self.foundations = foundations self.migrations = migrations def make_migration_manager(self, session): return MigrationManager( - self.name, self.models, self.migrations, session) + self.name, self.models, self.foundations, self.migrations, session) -def gather_database_data(media_types, plugins): +def gather_database_data(plugins): """ Gather all database data relevant to the extensions we have installed so we can do migrations and table initialization. @@ -54,17 +56,11 @@ def gather_database_data(media_types, plugins): # Add main first from mediagoblin.db.models import MODELS as MAIN_MODELS from mediagoblin.db.migrations import MIGRATIONS as MAIN_MIGRATIONS + from mediagoblin.db.models import FOUNDATIONS as MAIN_FOUNDATIONS managed_dbdata.append( DatabaseData( - u'__main__', MAIN_MODELS, MAIN_MIGRATIONS)) - - # Then get all registered media managers (eventually, plugins) - for media_type in media_types: - models = import_component('%s.models:MODELS' % media_type) - migrations = import_component('%s.migrations:MIGRATIONS' % media_type) - managed_dbdata.append( - DatabaseData(media_type, models, migrations)) + u'__main__', MAIN_MODELS, MAIN_FOUNDATIONS, MAIN_MIGRATIONS)) for plugin in plugins: try: @@ -78,6 +74,7 @@ def gather_database_data(media_types, plugins): except AttributeError as exc: _log.warning('Could not find MODELS in {0}.models, have you \ forgotten to add it? ({1})'.format(plugin, exc)) + models = [] try: migrations = import_component('{0}.migrations:MIGRATIONS'.format( @@ -89,12 +86,20 @@ forgotten to add it? ({1})'.format(plugin, exc)) migrations = {} except AttributeError as exc: - _log.debug('Cloud not find MIGRATIONS in {0}.migrations, have you \ + _log.debug('Could not find MIGRATIONS in {0}.migrations, have you \ forgotten to add it? ({1})'.format(plugin, exc)) + migrations = {} + + try: + foundations = import_component('{0}.models:FOUNDATIONS'.format(plugin)) + except ImportError as exc: + foundations = {} + except AttributeError as exc: + foundations = {} if models: managed_dbdata.append( - DatabaseData(plugin, models, migrations)) + DatabaseData(plugin, models, foundations, migrations)) return managed_dbdata @@ -108,14 +113,25 @@ def run_dbupdate(app_config, global_config): in the future, plugins) """ + # Set up the database + db = setup_connection_and_db_from_config(app_config, migrations=True) + #Run the migrations + run_all_migrations(db, app_config, global_config) + + +def run_all_migrations(db, app_config, global_config): + """ + Initializes or migrates a database that already has a + connection setup and also initializes or migrates all + extensions based on the config files. + + It can be used to initialize an in-memory database for + testing. + """ # Gather information from all media managers / projects dbdatas = gather_database_data( - app_config['media_types'], global_config.get('plugins', {}).keys()) - # Set up the database - db = setup_connection_and_db_from_config(app_config, migrations=True) - Session = sessionmaker(bind=db.engine) # Setup media managers for all dbdata, run init/migrate and print info diff --git a/mediagoblin/gmg_commands/import_export.py b/mediagoblin/gmg_commands/import_export.py index d51a1e3e..fbac09f6 100644 --- a/mediagoblin/gmg_commands/import_export.py +++ b/mediagoblin/gmg_commands/import_export.py @@ -16,6 +16,7 @@ from mediagoblin import mg_globals from mediagoblin.db.open import setup_connection_and_db_from_config +from mediagoblin.gmg_commands import util as commands_util from mediagoblin.storage.filestorage import BasicFileStorage from mediagoblin.init import setup_storage, setup_global_and_app_config @@ -63,7 +64,7 @@ def _import_media(db, args): # TODO: Add import of queue files queue_cache = BasicFileStorage(args._cache_path['queue']) - for entry in db.MediaEntry.find(): + for entry in db.MediaEntry.query.filter_by(): for name, path in entry.media_files.items(): _log.info('Importing: {0} - {1}'.format( entry.title.encode('ascii', 'replace'), @@ -204,7 +205,7 @@ def _export_media(db, args): # TODO: Add export of queue files queue_cache = BasicFileStorage(args._cache_path['queue']) - for entry in db.MediaEntry.find(): + for entry in db.MediaEntry.query.filter_by(): for name, path in entry.media_files.items(): _log.info(u'Exporting {0} - {1}'.format( entry.title, @@ -223,6 +224,7 @@ def env_export(args): ''' Export database and media files to a tar archive ''' + commands_util.check_unrecognized_args(args) if args.cache_path: if os.path.exists(args.cache_path): _log.error('The cache directory must not exist ' diff --git a/mediagoblin/gmg_commands/reprocess.py b/mediagoblin/gmg_commands/reprocess.py new file mode 100644 index 00000000..e2f19ea3 --- /dev/null +++ b/mediagoblin/gmg_commands/reprocess.py @@ -0,0 +1,302 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +import argparse +import os + +from mediagoblin import mg_globals +from mediagoblin.db.models import MediaEntry +from mediagoblin.gmg_commands import util as commands_util +from mediagoblin.submit.lib import run_process_media +from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ +from mediagoblin.tools.pluginapi import hook_handle +from mediagoblin.processing import ( + ProcessorDoesNotExist, ProcessorNotEligible, + get_entry_and_processing_manager, get_processing_manager_for_type, + ProcessingManagerDoesNotExist) + + +def reprocess_parser_setup(subparser): + subparser.add_argument( + '--celery', + action='store_true', + help="Don't process eagerly, pass off to celery") + + subparsers = subparser.add_subparsers(dest="reprocess_subcommand") + + ################### + # available command + ################### + available_parser = subparsers.add_parser( + "available", + help="Find out what actions are available for this media") + + available_parser.add_argument( + "id_or_type", + help="Media id or media type to check") + + available_parser.add_argument( + "--action-help", + action="store_true", + help="List argument help for each action available") + + available_parser.add_argument( + "--state", + help="The state of media you would like to reprocess") + + + ############# + # run command + ############# + + run_parser = subparsers.add_parser( + "run", + help="Run a reprocessing on one or more media") + + run_parser.add_argument( + 'media_id', + help="The media_entry id(s) you wish to reprocess.") + + run_parser.add_argument( + 'reprocess_command', + help="The reprocess command you intend to run") + + run_parser.add_argument( + 'reprocess_args', + nargs=argparse.REMAINDER, + help="rest of arguments to the reprocessing tool") + + + ################ + # thumbs command + ################ + thumbs = subparsers.add_parser( + 'thumbs', + help='Regenerate thumbs for all processed media') + + thumbs.add_argument( + '--size', + nargs=2, + type=int, + metavar=('max_width', 'max_height')) + + ################# + # initial command + ################# + subparsers.add_parser( + 'initial', + help='Reprocess all failed media') + + ################## + # bulk_run command + ################## + bulk_run_parser = subparsers.add_parser( + 'bulk_run', + help='Run reprocessing on a given media type or state') + + bulk_run_parser.add_argument( + 'type', + help='The type of media you would like to process') + + bulk_run_parser.add_argument( + '--state', + default='processed', + nargs='?', + help='The state of the media you would like to process. Defaults to' \ + " 'processed'") + + bulk_run_parser.add_argument( + 'reprocess_command', + help='The reprocess command you intend to run') + + bulk_run_parser.add_argument( + 'reprocess_args', + nargs=argparse.REMAINDER, + help='The rest of the arguments to the reprocessing tool') + + ############### + # help command? + ############### + + +def available(args): + # Get the media type, either by looking up media id, or by specific type + try: + media_id = int(args.id_or_type) + media_entry, manager = get_entry_and_processing_manager(media_id) + media_type = media_entry.media_type + except ValueError: + media_type = args.id_or_type + media_entry = None + manager = get_processing_manager_for_type(media_type) + except ProcessingManagerDoesNotExist: + entry = MediaEntry.query.filter_by(id=args.id_or_type).first() + print 'No such processing manager for {0}'.format(entry.media_type) + + if args.state: + processors = manager.list_all_processors_by_state(args.state) + elif media_entry is None: + processors = manager.list_all_processors() + else: + processors = manager.list_eligible_processors(media_entry) + + print "Available processors:" + print "=====================" + print "" + + if args.action_help: + for processor in processors: + print processor.name + print "-" * len(processor.name) + + parser = processor.generate_parser() + parser.print_help() + print "" + + else: + for processor in processors: + if processor.description: + print " - %s: %s" % (processor.name, processor.description) + else: + print " - %s" % processor.name + + +def run(args, media_id=None): + if not media_id: + media_id = args.media_id + try: + media_entry, manager = get_entry_and_processing_manager(media_id) + + # TODO: (maybe?) This could probably be handled entirely by the + # processor class... + try: + processor_class = manager.get_processor( + args.reprocess_command, media_entry) + except ProcessorDoesNotExist: + print 'No such processor "%s" for media with id "%s"' % ( + args.reprocess_command, media_entry.id) + return + except ProcessorNotEligible: + print 'Processor "%s" exists but media "%s" is not eligible' % ( + args.reprocess_command, media_entry.id) + return + + reprocess_parser = processor_class.generate_parser() + reprocess_args = reprocess_parser.parse_args(args.reprocess_args) + reprocess_request = processor_class.args_to_request(reprocess_args) + run_process_media( + media_entry, + reprocess_action=args.reprocess_command, + reprocess_info=reprocess_request) + + except ProcessingManagerDoesNotExist: + entry = MediaEntry.query.filter_by(id=media_id).first() + print 'No such processing manager for {0}'.format(entry.media_type) + + +def bulk_run(args): + """ + Bulk reprocessing of a given media_type + """ + query = MediaEntry.query.filter_by(media_type=args.type, + state=args.state) + + for entry in query: + run(args, entry.id) + + +def thumbs(args): + """ + Regenerate thumbs for all processed media + """ + query = MediaEntry.query.filter_by(state='processed') + + for entry in query: + try: + media_entry, manager = get_entry_and_processing_manager(entry.id) + + # TODO: (maybe?) This could probably be handled entirely by the + # processor class... + try: + processor_class = manager.get_processor( + 'resize', media_entry) + except ProcessorDoesNotExist: + print 'No such processor "%s" for media with id "%s"' % ( + 'resize', media_entry.id) + return + except ProcessorNotEligible: + print 'Processor "%s" exists but media "%s" is not eligible' % ( + 'resize', media_entry.id) + return + + reprocess_parser = processor_class.generate_parser() + + # prepare filetype and size to be passed into reprocess_parser + if args.size: + extra_args = 'thumb --{0} {1} {2}'.format( + processor_class.thumb_size, + args.size[0], + args.size[1]) + else: + extra_args = 'thumb' + + reprocess_args = reprocess_parser.parse_args(extra_args.split()) + reprocess_request = processor_class.args_to_request(reprocess_args) + run_process_media( + media_entry, + reprocess_action='resize', + reprocess_info=reprocess_request) + + except ProcessingManagerDoesNotExist: + print 'No such processing manager for {0}'.format(entry.media_type) + + +def initial(args): + """ + Reprocess all failed media + """ + query = MediaEntry.query.filter_by(state='failed') + + for entry in query: + try: + media_entry, manager = get_entry_and_processing_manager(entry.id) + run_process_media( + media_entry, + reprocess_action='initial') + except ProcessingManagerDoesNotExist: + print 'No such processing manager for {0}'.format(entry.media_type) + + +def reprocess(args): + # Run eagerly unless explicetly set not to + if not args.celery: + os.environ['CELERY_ALWAYS_EAGER'] = 'true' + + commands_util.setup_app(args) + + if args.reprocess_subcommand == "run": + run(args) + + elif args.reprocess_subcommand == "available": + available(args) + + elif args.reprocess_subcommand == "bulk_run": + bulk_run(args) + + elif args.reprocess_subcommand == "thumbs": + thumbs(args) + + elif args.reprocess_subcommand == "initial": + initial(args) diff --git a/mediagoblin/gmg_commands/theme.py b/mediagoblin/gmg_commands/theme.py deleted file mode 100644 index 71abb982..00000000 --- a/mediagoblin/gmg_commands/theme.py +++ /dev/null @@ -1,122 +0,0 @@ -# GNU MediaGoblin -- federated, autonomous media hosting -# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -import os - -from mediagoblin.init import setup_global_and_app_config -from mediagoblin.tools.theme import register_themes -from mediagoblin.tools.translate import pass_to_ugettext as _ -from mediagoblin.tools.common import simple_printer - - -def theme_parser_setup(subparser): - theme_subparsers = subparser.add_subparsers( - dest=u"subcommand", - help=u'Theme sub-commands') - - # Install command - install_parser = theme_subparsers.add_parser( - u'install', help=u'Install a theme to this mediagoblin instance') - install_parser.add_argument( - u'themefile', help=u'The theme archive to be installed') - - theme_subparsers.add_parser( - u'assetlink', - help=( - u"Link the currently installed theme's assets " - u"to the served theme asset directory")) - - -########### -# Utilities -########### - -def link_assets(theme, link_dir, printer=simple_printer): - """ - Returns a list of string of text telling the user what we did - which should be printable. - """ - link_dir = link_dir.rstrip(os.path.sep) - link_parent_dir = os.path.dirname(link_dir) - - results = [] - - if theme is None: - printer(_("Cannot link theme... no theme set\n")) - return results - - def _maybe_unlink_link_dir(): - """unlink link directory if it exists""" - if os.path.lexists(link_dir) \ - and os.path.islink(link_dir): - os.unlink(link_dir) - return True - - return results - - if theme.get('assets_dir') is None: - printer(_("No asset directory for this theme\n")) - if _maybe_unlink_link_dir(): - printer( - _("However, old link directory symlink found; removed.\n")) - return results - - _maybe_unlink_link_dir() - - # make the link directory parent dirs if necessary - if not os.path.lexists(link_parent_dir): - os.makedirs(link_parent_dir) - - os.symlink( - theme['assets_dir'].rstrip(os.path.sep), - link_dir) - printer("Linked the theme's asset directory:\n %s\nto:\n %s\n" % ( - theme['assets_dir'], link_dir)) - - -def install_theme(install_dir, themefile): - pass # TODO ;) - - -############# -# Subcommands -############# - -def assetlink_command(args): - """ - Link the asset directory of the currently installed theme - """ - global_config, app_config = setup_global_and_app_config(args.conf_file) - theme_registry, current_theme = register_themes(app_config) - link_assets(current_theme, app_config['theme_linked_assets_dir']) - - -def install_command(args): - """ - Handle the 'install this theme' subcommand - """ - global_config, app_config = setup_global_and_app_config(args.conf_file) - install_dir = app_config['theme_install_dir'] - install_theme(install_dir, args.themefile) - - -SUBCOMMANDS = { - 'assetlink': assetlink_command, - 'install': install_command} - - -def theme(args): - SUBCOMMANDS[args.subcommand](args) diff --git a/mediagoblin/gmg_commands/users.py b/mediagoblin/gmg_commands/users.py index 024c8498..4a730d9e 100644 --- a/mediagoblin/gmg_commands/users.py +++ b/mediagoblin/gmg_commands/users.py @@ -15,7 +15,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. from mediagoblin.gmg_commands import util as commands_util -from mediagoblin.auth import lib as auth_lib +from mediagoblin import auth from mediagoblin import mg_globals def adduser_parser_setup(subparser): @@ -40,9 +40,9 @@ def adduser(args): db = mg_globals.database users_with_username = \ - db.User.find({ - 'username': args.username.lower(), - }).count() + db.User.query.filter_by( + username=args.username.lower() + ).count() if users_with_username: print u'Sorry, a user with that name already exists.' @@ -52,9 +52,18 @@ def adduser(args): entry = db.User() entry.username = unicode(args.username.lower()) entry.email = unicode(args.email) - entry.pw_hash = auth_lib.bcrypt_gen_password_hash(args.password) - entry.status = u'active' - entry.email_verified = True + entry.pw_hash = auth.gen_password_hash(args.password) + default_privileges = [ + db.Privilege.query.filter( + db.Privilege.privilege_name==u'commenter').one(), + db.Privilege.query.filter( + db.Privilege.privilege_name==u'uploader').one(), + db.Privilege.query.filter( + db.Privilege.privilege_name==u'reporter').one(), + db.Privilege.query.filter( + db.Privilege.privilege_name==u'active').one() + ] + entry.all_privileges = default_privileges entry.save() print "User created (and email marked as verified)" @@ -71,9 +80,13 @@ def makeadmin(args): db = mg_globals.database - user = db.User.one({'username': unicode(args.username.lower())}) + user = db.User.query.filter_by( + username=unicode(args.username.lower())).one() if user: - user.is_admin = True + user.all_privileges.append( + db.Privilege.query.filter( + db.Privilege.privilege_name==u'admin').one() + ) user.save() print 'The user is now Admin' else: @@ -94,9 +107,10 @@ def changepw(args): db = mg_globals.database - user = db.User.one({'username': unicode(args.username.lower())}) + user = db.User.query.filter_by( + username=unicode(args.username.lower())).one() if user: - user.pw_hash = auth_lib.bcrypt_gen_password_hash(args.password) + user.pw_hash = auth.gen_password_hash(args.password) user.save() print 'Password successfully changed' else: diff --git a/mediagoblin/gmg_commands/util.py b/mediagoblin/gmg_commands/util.py index 6a6853d5..63e39ca9 100644 --- a/mediagoblin/gmg_commands/util.py +++ b/mediagoblin/gmg_commands/util.py @@ -36,5 +36,5 @@ def prompt_if_not_set(variable, text, password=False): variable=raw_input(text + u' ') else: variable=getpass.getpass(text + u' ') - + return variable |