diff --git a/frappe/config/desktop.py b/frappe/config/desktop.py
index fb655a2c3b..fa17ffa449 100644
--- a/frappe/config/desktop.py
+++ b/frappe/config/desktop.py
@@ -46,7 +46,7 @@ def get_data():
"type": "list"
},
"File Manager": {
- "color": "#95a5a6",
+ "color": "#905df5",
"doctype": "File",
"icon": "icon-folder-close",
"icon": "octicon octicon-file-directory",
diff --git a/frappe/core/doctype/file/file.js b/frappe/core/doctype/file/file.js
index b5f0133048..7f05e2ff9a 100644
--- a/frappe/core/doctype/file/file.js
+++ b/frappe/core/doctype/file/file.js
@@ -1,19 +1,21 @@
-frappe.ui.form.on("File", "onload", function(frm) {
- if(frappe.utils.is_image_file(frm.doc.file_url)){
- frm.doc.preview = '
\
-

\
-
';
- frm.refresh_field("preview");
- }
-})
-
frappe.ui.form.on("File", "refresh", function(frm) {
- frm.add_custom_button(__('Download'), function(){
- window.open(frm.doc.file_url);
- }, "icon-download");
-})
+ if(!frm.doc.is_folder) {
+ frm.add_custom_button(__('Download'), function() {
+ window.open(frm.doc.file_url);
+ }, "icon-download");
+ }
+
+ var wrapper = frm.get_field("preview_html").$wrapper;
+ var is_viewable = frappe.utils.is_image_file(frm.doc.file_url);
+
+ frm.toggle_display("preview", is_viewable);
+ frm.toggle_display("preview_html", is_viewable);
-// frappe.ui.form.on("File", "download", function(frm) {
-// window.open(frm.doc.file_url);
-// })
+ if(is_viewable){
+ wrapper.html('\
+

\
+
');
+ } else {
+ wrapper.empty();
+ }
+});
diff --git a/frappe/core/doctype/file/file.json b/frappe/core/doctype/file/file.json
index 61d8930b4b..c9ff215cb9 100644
--- a/frappe/core/doctype/file/file.json
+++ b/frappe/core/doctype/file/file.json
@@ -1,7 +1,7 @@
{
"allow_copy": 0,
"allow_import": 1,
- "allow_rename": 1,
+ "allow_rename": 0,
"autoname": "hash",
"creation": "2012-12-12 11:19:22",
"custom": 0,
@@ -24,6 +24,28 @@
"oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 0,
+ "read_only": 1,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "preview",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Preview",
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
@@ -35,13 +57,34 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "fieldname": "is_folder",
- "fieldtype": "Check",
+ "fieldname": "preview_html",
+ "fieldtype": "HTML",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Preview HTML",
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "section_break_5",
+ "fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
- "label": "Is Folder",
"no_copy": 0,
"permlevel": 0,
"precision": "",
@@ -80,14 +123,35 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "depends_on": "eval:!doc.is_folder",
- "fieldname": "file_url",
- "fieldtype": "Data",
- "hidden": 0,
+ "fieldname": "is_attachments_folder",
+ "fieldtype": "Check",
+ "hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
- "label": "File URL",
+ "label": "Is Attachments Folder",
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "file_size",
+ "fieldtype": "Int",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "File Size",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
@@ -119,13 +183,35 @@
"set_only_once": 0,
"unique": 0
},
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "depends_on": "eval:!doc.is_folder",
+ "fieldname": "file_url",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "File URL",
+ "no_copy": 0,
+ "permlevel": 0,
+ "print_hide": 0,
+ "read_only": 1,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "folder",
"fieldtype": "Link",
- "hidden": 0,
+ "hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
@@ -135,7 +221,7 @@
"permlevel": 0,
"precision": "",
"print_hide": 0,
- "read_only": 0,
+ "read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -146,15 +232,16 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "fieldname": "file_size",
- "fieldtype": "Int",
+ "fieldname": "is_folder",
+ "fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
- "in_list_view": 1,
- "label": "File Size",
+ "in_list_view": 0,
+ "label": "Is Folder",
"no_copy": 0,
"permlevel": 0,
+ "precision": "",
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
@@ -167,6 +254,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "depends_on": "eval:!doc.is_folder",
"fieldname": "section_break_8",
"fieldtype": "Section Break",
"hidden": 0,
@@ -345,7 +433,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
- "modified": "2015-09-08 15:57:09.103049",
+ "modified": "2015-09-18 06:22:10.902847",
"modified_by": "Administrator",
"module": "Core",
"name": "File",
@@ -370,6 +458,26 @@
"share": 1,
"submit": 0,
"write": 1
+ },
+ {
+ "amend": 0,
+ "apply_user_permissions": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 1,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "All",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
+ "write": 1
}
],
"read_only": 0,
diff --git a/frappe/core/doctype/file/file.py b/frappe/core/doctype/file/file.py
index d5480598fd..944b0891c3 100644
--- a/frappe/core/doctype/file/file.py
+++ b/frappe/core/doctype/file/file.py
@@ -30,7 +30,7 @@ class File(NestedSet):
path = get_breadcrumbs(self.folder)
folder_name = frappe.get_value("File", self.folder, "file_name")
return "/".join([d.file_name for d in path] + [folder_name, self.file_name])
-
+
def set_name(self):
"""Set name for folder"""
if self.is_folder:
@@ -44,14 +44,14 @@ class File(NestedSet):
def after_insert(self):
self.update_parent_folder_size()
-
+
def after_rename(self, olddn, newdn, merge=False):
for successor in self.get_successor():
setup_folder_path(successor, self.name)
-
+
def get_successor(self):
return frappe.db.sql_list("select name from tabFile where folder='%s'"%self.name) or []
-
+
def validate(self):
self.validate_duplicate_entry()
self.validate_folder()
@@ -83,52 +83,7 @@ class File(NestedSet):
def set_folder_name(self):
"""Make parent folders if not exists based on reference doctype and name"""
if self.attached_to_doctype and not self.folder:
- self.folder = self.get_parent_folder_name()
-
- def get_parent_folder_name(self):
- """Returns parent folder name. If not exists, then make"""
- doctype_folder_name = self.get_doctype_folder_name()
- parent_folder_name = frappe.db.get_value("File", {"file_name": self.attached_to_name,
- "is_folder": 1, "folder": doctype_folder_name})
-
- return self.make_folder(parent_folder_name, doctype_folder_name,
- self.attached_to_name)
-
- def get_doctype_folder_name(self):
- """Returns doctype folder name. If not exists, then make"""
- module_folder_name = self.get_module_folder_name()
- doctype_folder_name = frappe.db.get_value("File", {"file_name": self.attached_to_doctype,
- "is_folder": 1, "folder": module_folder_name})
-
- return self.make_folder(doctype_folder_name, module_folder_name,
- _(self.attached_to_doctype, frappe.db.get_default("lang")))
-
- def get_module_folder_name(self):
- """Returns module folder name. If not exists, then make"""
- if self.attached_to_doctype:
- module = frappe.db.get_value("DocType", self.attached_to_doctype, "module")
-
- home_folder_name = frappe.db.get_value("File", {"is_home_folder": 1})
-
- module_folder_name = frappe.db.get_value("File", {"file_name": module,
- "is_folder": 1, "folder": home_folder_name})
-
- return self.make_folder(module_folder_name, home_folder_name, _(module,
- frappe.db.get_default("lang")))
-
- def make_folder(self, name, folder, file_name):
- if not name:
- # parent folder
- file = frappe.get_doc({
- "doctype": "File",
- "is_folder": 1,
- "file_name": file_name,
- "folder": folder
- }).insert()
-
- name = file.name
-
- return name
+ self.folder = frappe.db.get_value("File", {"is_attachments_folder": 1})
def validate_folder(self):
if not self.is_home_folder and not self.folder and \
@@ -188,13 +143,21 @@ def on_doctype_update():
frappe.db.add_index("File", ["attached_to_doctype", "attached_to_name"])
def make_home_folder():
- frappe.get_doc({
+ home = frappe.get_doc({
"doctype": "File",
"is_folder": 1,
"is_home_folder": 1,
"file_name": _("Home")
}).insert()
+ frappe.get_doc({
+ "doctype": "File",
+ "folder": home.name,
+ "is_folder": 1,
+ "is_attachments_folder": 1,
+ "file_name": _("Attachments")
+ }).insert()
+
@frappe.whitelist()
def get_breadcrumbs(folder):
"""returns name, file_name of parent folder"""
@@ -221,11 +184,11 @@ def move_file(file_list, new_parent, old_parent):
frappe.get_doc("File", new_parent).save()
return "File(s) has been moved successfully!!"
-
+
def setup_folder_path(filename, new_parent):
file = frappe.get_doc("File", filename)
file.folder = new_parent
file.save()
-
+
if file.is_folder:
- frappe.rename_doc("File", file.name, file.get_name_based_on_parent_folder())
\ No newline at end of file
+ frappe.rename_doc("File", file.name, file.get_name_based_on_parent_folder())
diff --git a/frappe/core/doctype/file/file_list.js b/frappe/core/doctype/file/file_list.js
index b84f6f221a..20b860fa7d 100644
--- a/frappe/core/doctype/file/file_list.js
+++ b/frappe/core/doctype/file/file_list.js
@@ -32,7 +32,7 @@ frappe.listview_settings['File'] = {
doclist.breadcrumb = $('
')
.insertBefore(doclist.filter_area);
- doclist.listview.settings.setup_new_folder(doclist);
+ doclist.listview.settings.setup_menu(doclist);
doclist.listview.settings.setup_dragdrop(doclist);
doclist.$page.on("click", ".list-delete", function(event) {
@@ -52,7 +52,7 @@ frappe.listview_settings['File'] = {
});
});
},
- setup_new_folder: function(doclist) {
+ setup_menu: function(doclist) {
doclist.page.add_menu_item(__("New Folder"), function() {
var d = frappe.prompt(__("Name"), function(values) {
if((values.value.indexOf("/") > -1)){
@@ -70,6 +70,10 @@ frappe.listview_settings['File'] = {
})
}, __('Enter folder name'), __("Create"));
});
+
+ doclist.page.add_menu_item(__("Edit Folder"), function() {
+ frappe.set_route("Form", "File", doclist.current_folder);
+ });
},
setup_dragdrop: function(doclist) {
$(doclist.$page).on('dragenter dragover', false)
@@ -153,7 +157,9 @@ frappe.listview_settings['File'] = {
doclist.filter_list.add_filter("File", "folder", "=", doclist.current_folder, true);
doclist.dirty = true;
+ doclist.fresh = false;
+ doclist.page.set_title(doclist.current_folder_name);
frappe.utils.set_title(doclist.current_folder_name);
},
set_primary_action:function(doclist){
@@ -165,7 +171,6 @@ frappe.listview_settings['File'] = {
"from_form": 1
},
callback: function() {
- console.log('here')
doclist.refresh();
}
});
diff --git a/frappe/patches/v6_1/rename_file_data.py b/frappe/patches/v6_1/rename_file_data.py
index 6e7c163182..9c2a8edc3b 100644
--- a/frappe/patches/v6_1/rename_file_data.py
+++ b/frappe/patches/v6_1/rename_file_data.py
@@ -7,7 +7,7 @@ def execute():
frappe.rename_doc("DocType", "File Data", "File")
frappe.reload_doctype("File")
- # DELETE THIS
+ # TODO: DELETE THIS
frappe.db.sql("""delete from tabFile where is_folder=1""")
frappe.db.sql("""update tabFile set folder=null""")
diff --git a/frappe/permissions.py b/frappe/permissions.py
index 0122fbde98..c534cd15c3 100644
--- a/frappe/permissions.py
+++ b/frappe/permissions.py
@@ -52,6 +52,7 @@ def has_permission(doctype, ptype="read", doc=None, verbose=False, user=None):
if doc_name in shared:
if verbose: print "Shared"
if ptype in ("read", "write", "share") or meta.permissions[0].get(ptype):
+ if verbose: print "Is shared"
return True
elif shared:
@@ -60,6 +61,7 @@ def has_permission(doctype, ptype="read", doc=None, verbose=False, user=None):
if verbose: print "Has a shared document"
return True
+ if verbose: print "Not Shared"
return False
role_permissions = get_role_permissions(meta, user=user, verbose=verbose)
@@ -67,28 +69,40 @@ def has_permission(doctype, ptype="read", doc=None, verbose=False, user=None):
if not role_permissions.get(ptype):
return false_if_not_shared()
+ perm = True
+
if doc:
if isinstance(doc, basestring):
doc = frappe.get_doc(meta.name, doc)
- # if owner match, then return True
- if doc.owner == frappe.session.user and role_permissions["if_owner"].get(ptype) and ptype!="create":
- return True
+ owner_perm = user_perm = controller_perm = None
+
+ if role_permissions["if_owner"].get(ptype) and ptype!="create":
+ owner_perm = doc.owner == frappe.session.user
+ if verbose: print "Owner permission: {0}".format(owner_perm)
# check if user permission
- if role_permissions["apply_user_permissions"].get(ptype):
- if not user_has_permission(doc, verbose=verbose, user=user,
- user_permission_doctypes=role_permissions.get("user_permission_doctypes", {}).get(ptype) or []):
- if verbose: print "No user permission"
- return false_if_not_shared()
-
- if not has_controller_permissions(doc, ptype, user=user):
- if verbose: print "No controller permission"
- return false_if_not_shared()
-
- if verbose:
- print "Has Role"
- return True
+ if not owner_perm and role_permissions["apply_user_permissions"].get(ptype):
+ user_perm = user_has_permission(doc, verbose=verbose, user=user,
+ user_permission_doctypes=role_permissions.get("user_permission_doctypes", {}).get(ptype) or [])
+
+ if verbose: print "User permission: {0}".format(user_perm)
+
+ if not owner_perm and not user_perm:
+ controller_perm = has_controller_permissions(doc, ptype, user=user)
+
+ if verbose: print "Controller permission: {0}".format(controller_perm)
+
+ # permission true if any one condition is explicitly True or all permissions are undefined (None)
+ perm = any([owner_perm, user_perm, controller_perm]) or \
+ all([owner_perm==None, user_perm==None, controller_perm==None])
+
+ if not perm:
+ perm = false_if_not_shared()
+
+ if verbose: print "Final Permission: {0}".format(perm)
+
+ return perm
def get_doc_permissions(doc, verbose=False, user=None):
"""Returns a dict of evaluated permissions for given `doc` like `{"read":1, "write":1}`"""
@@ -271,9 +285,15 @@ def user_has_permission(doc, verbose=True, user=None, user_permission_doctypes=N
return _user_has_permission
def has_controller_permissions(doc, ptype, user=None):
+ """Returns controller permissions if defined. None if not defined"""
if not user: user = frappe.session.user
- for method in frappe.get_hooks("has_permission").get(doc.doctype, []):
+ methods = frappe.get_hooks("has_permission").get(doc.doctype, [])
+
+ if not methods:
+ return None
+
+ for method in methods:
if not frappe.call(frappe.get_attr(method), doc=doc, ptype=ptype, user=user):
return False
diff --git a/frappe/public/js/frappe/model/perm.js b/frappe/public/js/frappe/model/perm.js
index 028d4c586f..a76bf01658 100644
--- a/frappe/public/js/frappe/model/perm.js
+++ b/frappe/public/js/frappe/model/perm.js
@@ -60,6 +60,20 @@ $.extend(frappe.perm, {
});
}
+ // if owner
+ if(!$.isEmptyObject(perm[0].if_owner)) {
+ if(doc.owner===user) {
+ $.extend(perm[0], perm[0].if_owner);
+ } else {
+ // not owner, remove permissions
+ $.each(perm[0].if_owner, function(ptype, value) {
+ if(perm[0].if_owner[ptype]) {
+ perm[0][ptype] = 0
+ }
+ })
+ }
+ }
+
// apply permissions from shared
if(docinfo.shared) {
for(var i=0; i%(label)s',
- {doctype: breadcrumbs.doctype, label: __(breadcrumbs.doctype)}))
+ route = (cur_frm && cur_frm.list_route) || ("List/" + breadcrumbs.doctype)
+ $(repl('%(label)s',
+ {route: route, label: __(breadcrumbs.doctype)}))
.appendTo($breadcrumbs);
}
}