You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

341 line
10 KiB

  1. # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
  2. # MIT License. See license.txt
  3. from __future__ import unicode_literals
  4. import frappe, json
  5. from frappe import _dict
  6. import frappe.share
  7. from frappe.utils import cint
  8. from frappe.permissions import get_roles, get_valid_perms
  9. class UserPermissions:
  10. """
  11. A user permission object can be accessed as `frappe.get_user()`
  12. """
  13. def __init__(self, name=''):
  14. self.defaults = None
  15. self.name = name or frappe.session.get('user')
  16. self.roles = []
  17. self.all_read = []
  18. self.can_create = []
  19. self.can_read = []
  20. self.can_write = []
  21. self.can_cancel = []
  22. self.can_delete = []
  23. self.can_search = []
  24. self.can_get_report = []
  25. self.can_import = []
  26. self.can_export = []
  27. self.can_print = []
  28. self.can_email = []
  29. self.can_set_user_permissions = []
  30. self.allow_modules = []
  31. self.in_create = []
  32. self.setup_user()
  33. def setup_user(self):
  34. def get_user_doc():
  35. user = None
  36. try:
  37. user = frappe.get_doc("User", self.name).as_dict()
  38. except frappe.DoesNotExistError:
  39. pass
  40. except Exception, e:
  41. # install boo-boo
  42. if e.args[0] != 1146: raise
  43. return user
  44. if not frappe.flags.in_install_db and not frappe.flags.in_test:
  45. user_doc = frappe.cache().hget("user_doc", self.name, get_user_doc)
  46. if user_doc:
  47. self.doc = frappe.get_doc(user_doc)
  48. def get_roles(self):
  49. """get list of roles"""
  50. if not self.roles:
  51. self.roles = get_roles(self.name)
  52. return self.roles
  53. def build_doctype_map(self):
  54. """build map of special doctype properties"""
  55. self.doctype_map = {}
  56. for r in frappe.db.sql("""select name, in_create, issingle, istable,
  57. read_only, module from tabDocType""", as_dict=1):
  58. self.doctype_map[r['name']] = r
  59. def build_perm_map(self):
  60. """build map of permissions at level 0"""
  61. self.perm_map = {}
  62. for r in get_valid_perms():
  63. dt = r['parent']
  64. if not dt in self.perm_map:
  65. self.perm_map[dt] = {}
  66. for k in frappe.permissions.rights:
  67. if not self.perm_map[dt].get(k):
  68. self.perm_map[dt][k] = r.get(k)
  69. def build_permissions(self):
  70. """build lists of what the user can read / write / create
  71. quirks:
  72. read_only => Not in Search
  73. in_create => Not in create
  74. """
  75. self.build_doctype_map()
  76. self.build_perm_map()
  77. user_shared = frappe.share.get_shared_doctypes()
  78. no_list_view_link = []
  79. for dt in self.doctype_map:
  80. dtp = self.doctype_map[dt]
  81. p = self.perm_map.get(dt, {})
  82. if not p.get("read") and (dt in user_shared):
  83. p["read"] = 1
  84. if not dtp.get('istable'):
  85. if p.get('create') and not dtp.get('issingle'):
  86. if dtp.get('in_create'):
  87. self.in_create.append(dt)
  88. else:
  89. self.can_create.append(dt)
  90. elif p.get('write'):
  91. self.can_write.append(dt)
  92. elif p.get('read'):
  93. if dtp.get('read_only'):
  94. # read_only = "User Cannot Search"
  95. self.all_read.append(dt)
  96. no_list_view_link.append(dt)
  97. else:
  98. self.can_read.append(dt)
  99. if p.get('cancel'):
  100. self.can_cancel.append(dt)
  101. if p.get('delete'):
  102. self.can_delete.append(dt)
  103. if (p.get('read') or p.get('write') or p.get('create')):
  104. if p.get('report'):
  105. self.can_get_report.append(dt)
  106. for key in ("import", "export", "print", "email", "set_user_permissions"):
  107. if p.get(key):
  108. getattr(self, "can_" + key).append(dt)
  109. if not dtp.get('istable'):
  110. if not dtp.get('issingle') and not dtp.get('read_only'):
  111. self.can_search.append(dt)
  112. if not dtp.get('module') in self.allow_modules:
  113. self.allow_modules.append(dtp.get('module'))
  114. self.can_write += self.can_create
  115. self.can_write += self.in_create
  116. self.can_read += self.can_write
  117. self.shared = frappe.db.sql_list("""select distinct share_doctype from `tabDocShare`
  118. where `user`=%s and `read`=1""", self.name)
  119. self.can_read = list(set(self.can_read + self.shared))
  120. self.all_read += self.can_read
  121. for dt in no_list_view_link:
  122. if dt in self.can_read:
  123. self.can_read.remove(dt)
  124. if "System Manager" in self.get_roles():
  125. self.can_import = filter(lambda d: d in self.can_create,
  126. frappe.db.sql_list("""select name from `tabDocType` where allow_import = 1"""))
  127. def get_defaults(self):
  128. import frappe.defaults
  129. self.defaults = frappe.defaults.get_defaults(self.name)
  130. return self.defaults
  131. # update recent documents
  132. def update_recent(self, dt, dn):
  133. rdl = frappe.cache().hget("user_recent", self.name) or []
  134. new_rd = [dt, dn]
  135. # clear if exists
  136. for i in range(len(rdl)):
  137. rd = rdl[i]
  138. if rd==new_rd:
  139. del rdl[i]
  140. break
  141. if len(rdl) > 19:
  142. rdl = rdl[:19]
  143. rdl = [new_rd] + rdl
  144. frappe.cache().hset("user_recent", self.name, rdl)
  145. def _get(self, key):
  146. if not self.can_read:
  147. self.build_permissions()
  148. return getattr(self, key)
  149. def get_can_read(self):
  150. """return list of doctypes that the user can read"""
  151. if not self.can_read:
  152. self.build_permissions()
  153. return self.can_read
  154. def load_user(self):
  155. d = frappe.db.sql("""select email, first_name, last_name,
  156. email_signature, user_type, language, background_image, background_style, mute_sounds
  157. from tabUser where name = %s""", (self.name,), as_dict=1)[0]
  158. if not self.can_read:
  159. self.build_permissions()
  160. d.name = self.name
  161. d.recent = json.dumps(frappe.cache().hget("user_recent", self.name) or [])
  162. d.roles = self.get_roles()
  163. d.defaults = self.get_defaults()
  164. for key in ("can_create", "can_write", "can_read", "can_cancel", "can_delete",
  165. "can_get_report", "allow_modules", "all_read", "can_search",
  166. "in_create", "can_export", "can_import", "can_print", "can_email",
  167. "can_set_user_permissions"):
  168. d[key] = list(set(getattr(self, key)))
  169. d.all_reports = self.get_all_reports()
  170. return d
  171. def get_all_reports(self):
  172. reports = frappe.db.sql("""select name, report_type, ref_doctype from tabReport
  173. where ref_doctype in ('{0}') and disabled = 0""".format("', '".join(self.can_get_report)), as_dict=1)
  174. return frappe._dict((d.name, d) for d in reports)
  175. def get_user_fullname(user):
  176. fullname = frappe.db.sql("SELECT CONCAT_WS(' ', first_name, last_name) FROM `tabUser` WHERE name=%s", (user,))
  177. return fullname and fullname[0][0] or ''
  178. def get_fullname_and_avatar(user):
  179. first_name, last_name, avatar, name = frappe.db.get_value("User",
  180. user, ["first_name", "last_name", "user_image", "name"])
  181. return _dict({
  182. "fullname": " ".join(filter(None, [first_name, last_name])),
  183. "avatar": avatar,
  184. "name": name
  185. })
  186. def get_system_managers(only_name=False):
  187. """returns all system manager's user details"""
  188. import email.utils
  189. from frappe.core.doctype.user.user import STANDARD_USERS
  190. system_managers = frappe.db.sql("""select distinct name,
  191. concat_ws(" ", if(first_name="", null, first_name), if(last_name="", null, last_name))
  192. as fullname from tabUser p
  193. where docstatus < 2 and enabled = 1
  194. and name not in ({})
  195. and exists (select * from tabUserRole ur
  196. where ur.parent = p.name and ur.role="System Manager")
  197. order by creation desc""".format(", ".join(["%s"]*len(STANDARD_USERS))),
  198. STANDARD_USERS, as_dict=True)
  199. if only_name:
  200. return [p.name for p in system_managers]
  201. else:
  202. return [email.utils.formataddr((p.fullname, p.name)) for p in system_managers]
  203. def add_role(user, role):
  204. frappe.get_doc("User", user).add_roles(role)
  205. def add_system_manager(email, first_name=None, last_name=None, send_welcome_email=False):
  206. # add user
  207. user = frappe.new_doc("User")
  208. user.update({
  209. "name": email,
  210. "email": email,
  211. "enabled": 1,
  212. "first_name": first_name or email,
  213. "last_name": last_name,
  214. "user_type": "System User",
  215. "send_welcome_email": 1 if send_welcome_email else 0
  216. })
  217. user.insert()
  218. # add roles
  219. roles = frappe.db.sql_list("""select name from `tabRole`
  220. where name not in ("Administrator", "Guest", "All")""")
  221. user.add_roles(*roles)
  222. def get_enabled_system_users():
  223. return frappe.db.sql("""select * from tabUser where
  224. user_type='System User' and enabled=1 and name not in ('Administrator', 'Guest')""", as_dict=1)
  225. def is_website_user():
  226. return frappe.db.get_value('User', frappe.session.user, 'user_type') == "Website User"
  227. def is_system_user(username):
  228. return frappe.db.get_value("User", {"name": username, "enabled": 1, "user_type": "System User"})
  229. def get_users():
  230. from frappe.core.doctype.user.user import get_system_users
  231. users = []
  232. system_managers = frappe.utils.user.get_system_managers(only_name=True)
  233. for user in get_system_users():
  234. users.append({
  235. "full_name": frappe.utils.user.get_user_fullname(user),
  236. "email": user,
  237. "is_system_manager": 1 if (user in system_managers) else 0
  238. })
  239. return users
  240. def set_last_active_to_now(user):
  241. from frappe.utils import now_datetime
  242. frappe.db.set_value("User", user, "last_active", now_datetime())
  243. def disable_users(limits=None):
  244. if not limits:
  245. return
  246. if limits.get('users'):
  247. system_manager = get_system_managers(only_name=True)[-1]
  248. #exclude system manager from active user list
  249. active_users = frappe.db.sql_list("""select name from tabUser
  250. where name not in ('Administrator', 'Guest', %s) and user_type = 'System User' and enabled=1
  251. order by creation desc""", system_manager)
  252. user_limit = cint(limits.get('users')) - 1
  253. if len(active_users) > user_limit:
  254. # if allowed user limit 1 then deactivate all additional users
  255. # else extract additional user from active user list and deactivate them
  256. if cint(limits.get('users')) != 1:
  257. active_users = active_users[:-1 * user_limit]
  258. for user in active_users:
  259. frappe.db.set_value("User", user, 'enabled', 0)
  260. from frappe.core.doctype.user.user import get_total_users
  261. if get_total_users() > cint(limits.get('users')):
  262. reset_simultaneous_sessions(cint(limits.get('users')))
  263. frappe.db.commit()
  264. def reset_simultaneous_sessions(user_limit):
  265. for user in frappe.db.sql("""select name, simultaneous_sessions from tabUser
  266. where name not in ('Administrator', 'Guest') and user_type = 'System User' and enabled=1
  267. order by creation desc""", as_dict=1):
  268. if user.simultaneous_sessions < user_limit:
  269. user_limit = user_limit - user.simultaneous_sessions
  270. else:
  271. frappe.db.set_value("User", user.name, "simultaneous_sessions", 1)
  272. user_limit = user_limit - 1