1
0
مراية لـ https://github.com/postalserver/postal.git تم المزامنة 2026-01-20 14:49:53 +00:00

refactor: user management

هذا الالتزام موجود في:
Adam Cooke
2021-07-27 16:55:20 +00:00
الأصل e9a52e9512
التزام daf469ce7f
27 ملفات معدلة مع 106 إضافات و359 حذوفات

عرض الملف

@@ -62,7 +62,6 @@ $ ->
else else
$('[data-credential-key-type=all]').show() $('[data-credential-key-type=all]').show()
$(document).on 'change', 'select#credential_type', -> $(document).on 'change', 'select#credential_type', ->
value = $(this).val() value = $(this).val()
toggleCredentialInputs(value) toggleCredentialInputs(value)

عرض الملف

@@ -5,7 +5,6 @@ class ApplicationController < ActionController::Base
protect_from_forgery with: :exception protect_from_forgery with: :exception
before_action :login_required before_action :login_required
before_action :verified_email_required
before_action :set_timezone before_action :set_timezone
rescue_from Authie::Session::InactiveSession, :with => :auth_session_error rescue_from Authie::Session::InactiveSession, :with => :auth_session_error
@@ -23,25 +22,13 @@ class ApplicationController < ActionController::Base
def admin_required def admin_required
if logged_in? if logged_in?
unless current_user.admin? unless current_user.admin?
render :text => "Not permitted" render :plain => "Not permitted"
end end
else else
redirect_to login_path(:return_to => request.fullpath) redirect_to login_path(:return_to => request.fullpath)
end end
end end
def verified_email_required
if logged_in? && !current_user.verified?
redirect_to verify_path(:return_to => request.fullpath)
end
end
def require_organization_admin
unless organization.admin?(current_user)
redirect_to organization_root_path(organization), :alert => "This page can only be accessed by the organization admins"
end
end
def require_organization_owner def require_organization_owner
unless organization.owner == current_user unless organization.owner == current_user
redirect_to organization_root_path(organization), :alert => "This page can only be accessed by the organization's owner (#{organization.owner.name})" redirect_to organization_root_path(organization), :alert => "This page can only be accessed by the organization's owner (#{organization.owner.name})"

عرض الملف

@@ -1,7 +1,6 @@
class OrganizationsController < ApplicationController class OrganizationsController < ApplicationController
before_action :admin_required, :only => [:new, :create] before_action :admin_required, :only => [:new, :create, :delete, :destroy]
before_action :require_organization_admin, :only => [:edit, :update, :delete, :destroy]
def index def index
if current_user.admin? if current_user.admin?

عرض الملف

@@ -2,7 +2,6 @@ class ServersController < ApplicationController
include WithinOrganization include WithinOrganization
before_action :require_organization_admin, :only => [:new, :create, :delete, :destroy]
before_action :admin_required, :only => [:advanced, :suspend, :unsuspend] before_action :admin_required, :only => [:advanced, :suspend, :unsuspend]
before_action { params[:id] && @server = organization.servers.present.find_by_permalink!(params[:id]) } before_action { params[:id] && @server = organization.servers.present.find_by_permalink!(params[:id]) }

عرض الملف

@@ -3,7 +3,6 @@ class SessionsController < ApplicationController
layout 'sub' layout 'sub'
skip_before_action :login_required, :only => [:new, :create, :create_with_token, :begin_password_reset, :finish_password_reset, :ip, :raise_error] skip_before_action :login_required, :only => [:new, :create, :create_with_token, :begin_password_reset, :finish_password_reset, :ip, :raise_error]
skip_before_action :verified_email_required
def create def create
login(User.authenticate(params[:email_address], params[:password])) login(User.authenticate(params[:email_address], params[:password]))

عرض الملف

@@ -1,7 +1,6 @@
class UserController < ApplicationController class UserController < ApplicationController
skip_before_action :login_required, :only => [:new, :create, :join] skip_before_action :login_required, :only => [:new, :create, :join]
skip_before_action :verified_email_required, :only => [:edit, :update, :verify]
def new def new
@user_invite = UserInvite.active.find_by!(:uuid => params[:invite_token]) @user_invite = UserInvite.active.find_by!(:uuid => params[:invite_token])

عرض الملف

@@ -1,63 +1,55 @@
class UsersController < ApplicationController class UsersController < ApplicationController
include WithinOrganization
before_action :require_organization_admin before_action :admin_required
before_action :require_organization_owner, :only => [:make_owner] before_action { params[:id] && @user = User.find_by!(uuid: params[:id]) }
before_action { params[:id] && @user = params[:invite].present? ? organization.user_invites.find_by_uuid!(params[:id]) : organization.users.find_by_uuid!(params[:id]) }
def index def index
@users = organization.organization_users.where(:user_type => 'User').includes(:user).to_a.sort_by { |u| "#{u.user.first_name}#{u.user.last_name}".upcase } @users = User.order(:first_name, :last_name).includes(:organization_users)
@pending_users = organization.organization_users.where(:user_type => "UserInvite").includes(:user).to_a.sort_by { |u| u.user.email_address.upcase }
end end
def new def new
@organization_user = organization.organization_users.build @user = User.new(admin: true)
end end
def create def create
@organization_user = organization.organization_users.build(params.require(:organization_user).permit(:email_address, :admin, :all_servers)) @user = User.new(params.require(:user).permit(:email_address, :first_name, :last_name, :password, :password_confirmation, :admin, organization_ids: []))
if @organization_user.save if @user.save
AppMailer.user_invite(@organization_user.user, organization).deliver redirect_to_with_json :users, :notice => "#{@user.name} has been created successfully."
redirect_to_with_json [organization, :users], :notice => "An invitation will be sent to #{@organization_user.user.email_address} which will allow them to access your organization."
else else
render_form_errors 'new', @organization_user render_form_errors 'new', @user
end end
end end
def edit def edit
@organization_user = organization.user_assignment(@user)
end end
def update def update
@organization_user = organization.user_assignment(@user) @user.attributes = params.require(:user).permit(:email_address, :first_name, :last_name, :admin, organization_ids: [])
if @organization_user.update(params.require(:organization_user).permit(:admin))
redirect_to_with_json [organization, :users], :notice => "Permissions for #{@organization_user.user.name} have been updated successfully." if @user == current_user && !@user.admin?
respond_to do |wants|
wants.html { redirect_to users_path, alert: "You cannot change your own admin status" }
wants.json { render :json => {:form_errors => ["You cannot change your own admin status"]}, :status => 422 }
end
return
end
if @user.save
redirect_to_with_json :users, :notice => "Permissions for #{@user.name} have been updated successfully."
else else
render_form_errors 'edit', @organization_user render_form_errors 'edit', @user
end end
end end
def destroy def destroy
if @user == current_user if @user == current_user
redirect_to_with_json [organization, :users], :alert => "You cannot revoke your own access." redirect_to_with_json :users, :alert => "You cannot delete your own user."
return return
end end
if @user == organization.owner @user.destroy!
redirect_to_with_json [organization, :users], :alert => "You cannot revoke the organization owner's access." redirect_to_with_json :users, :notice => "#{@user.name} has been removed"
return
end
organization.organization_users.where(:user => @user).destroy_all
redirect_to_with_json [organization, :users], :notice => "#{@user.name} has been removed from this organization"
end end
def make_owner
if @user.is_a?(User)
organization.make_owner(@user)
redirect_to_with_json [organization, :users], :notice => "#{@user.name} is now the owner of this organization."
else
raise Postal::Error, "User must be a User not a UserInvite to make owner"
end
end
end end

عرض الملف

@@ -69,20 +69,6 @@ class Organization < ApplicationRecord
suspended_at.present? suspended_at.present?
end end
def admin?(user)
user.admin? ||
!!(owner?(user) || user_assignment(user)&.admin?)
end
def owner?(user)
self.owner == user
end
def accessible_by?(user)
user.admin? ||
!!(user_assignment(user))
end
def user_assignment(user) def user_assignment(user)
@user_assignments ||= {} @user_assignments ||= {}
@user_assignments[user.id] ||= organization_users.where(:user => user).first @user_assignments[user.id] ||= organization_users.where(:user => user).first

عرض الملف

@@ -16,43 +16,4 @@ class OrganizationUser < ApplicationRecord
belongs_to :organization belongs_to :organization
belongs_to :user, :polymorphic => true, :optional => true belongs_to :user, :polymorphic => true, :optional => true
validate :validate_uniqueness
before_create :create_user_invite
after_destroy :remove_user_invites
def email_address
@email_address ||= user&.email_address
end
def email_address=(value)
@email_address = value
end
def create_user_invite
if self.user.nil?
user = UserInvite.where(:email_address => @email_address).first_or_initialize
if user.save
self.user = user
else
errors.add :base, user.errors.full_messages.to_sentence
throw :abort
end
end
end
def validate_uniqueness
if self.email_address.present?
if organization.organization_users.where.not(:id => self.id).any? { |ou| ou.user.email_address.upcase == self.email_address.upcase }
errors.add :email_address, "is already assigned or has an pending invite"
end
end
end
def remove_user_invites
if self.user.is_a?(UserInvite) && self.user.organizations.empty?
self.user.destroy
end
end
end end

عرض الملف

@@ -119,10 +119,6 @@ class Server < ApplicationRecord
end end
end end
def accessible_by?(user)
organization.accessible_by?(user)
end
def to_param def to_param
permalink permalink
end end

عرض الملف

@@ -31,7 +31,7 @@ class User < ApplicationRecord
validates :first_name, :presence => true validates :first_name, :presence => true
validates :last_name, :presence => true validates :last_name, :presence => true
validates :email_address, :presence => true, :uniqueness => true, :format => {:with => /@/} validates :email_address, :presence => true, :uniqueness => true, :format => {:with => /@/, allow_blank: true}
validates :time_zone, :presence => true validates :time_zone, :presence => true
default_value :time_zone, -> { 'UTC' } default_value :time_zone, -> { 'UTC' }
@@ -39,23 +39,6 @@ class User < ApplicationRecord
has_many :organization_users, :dependent => :destroy, :as => :user has_many :organization_users, :dependent => :destroy, :as => :user
has_many :organizations, :through => :organization_users has_many :organizations, :through => :organization_users
scope :verified, -> { where.not(:email_verified_at => nil) }
when_attribute :email_address, :changes_to => :anything do
before_save do |was, now|
unless self.new_record? && self.email_verified_at
self.email_verification_token = rand(999999).to_s.rjust(6, '0')
self.email_verified_at = nil
end
end
after_commit do |was, new|
if self.email_verified_at.nil? && was.present?
AppMailer.verify_email_address(self).deliver
end
end
end
def organizations_scope def organizations_scope
@organizations_scope ||= begin @organizations_scope ||= begin
if self.admin? if self.admin?
@@ -74,15 +57,6 @@ class User < ApplicationRecord
uuid uuid
end end
def verify!
self.email_verified_at = Time.now
self.save!
end
def verified?
email_verified_at.present?
end
def md5_for_gravatar def md5_for_gravatar
@md5_for_gravatar ||= Digest::MD5.hexdigest(email_address.to_s.downcase) @md5_for_gravatar ||= Digest::MD5.hexdigest(email_address.to_s.downcase)
end end
@@ -95,10 +69,6 @@ class User < ApplicationRecord
"#{name} <#{email_address}>" "#{name} <#{email_address}>"
end end
def generate_login_token
JWT.encode({'user' => self.id, 'timestamp' => Time.now.to_f}, Postal.signing_key.to_s, 'HS256')
end
def self.[](email) def self.[](email)
where(:email_address => email).first where(:email_address => email).first
end end

عرض الملف

@@ -1,12 +0,0 @@
Hello <%= @user.first_name %>,
To verify your e-mail address you will be prompted to enter a code when you login to your Postal account. The code you need to enter is:
<%= @user.email_verification_token %>
Once you've done that, you'll be able to access your account.
Thanks,
<%= Postal.smtp_from_name %>
<%= Postal.smtp_from_address %>

عرض الملف

@@ -1,10 +0,0 @@
You've been invited to access the <%= @organization.name %> organization on Postal.
To accept this invitation, please click the link below to create an account or login to an existing one.
<%= Postal.host_with_protocol %>/join/<%= @user_invite.uuid %>
Thanks,
<%= Postal.smtp_from_name %>
<%= Postal.smtp_from_address %>

عرض الملف

@@ -1,14 +0,0 @@
Hi <%= @user.first_name %>,
You've just changed the e-mail address on your Postal account. So that we can verify that you own the new address you've entered, we need you to enter the code below into the box shown in your web browser.
<%= @user.email_verification_token %>
If you don't have a box on your screen, just login to your Postal account to continue.
<%= Postal.host_with_protocol %>/login
Thanks,
<%= Postal.smtp_from_name %>
<%= Postal.smtp_from_address %>

عرض الملف

@@ -29,18 +29,20 @@
%li.siteHeader__navItem.siteHeader__navItem--organization %li.siteHeader__navItem.siteHeader__navItem--organization
= link_to organization.name, organization_root_path(organization), :class => 'siteHeader__navLinkWithMenu' = link_to organization.name, organization_root_path(organization), :class => 'siteHeader__navLinkWithMenu'
%ul.siteHeader__subMenu %ul.siteHeader__subMenu
%li.siteHeader__subMenuItem.siteHeader__subMenuItem--header= link_to organization.name, organization_settings_path(organization) %li.siteHeader__subMenuItem.siteHeader__subMenuItem--header= link_to organization.name, organization_root_path(organization)
- if organization.admin?(current_user) %li.siteHeader__subMenuItem= link_to "Mail servers", organization_root_path(organization), :class => 'siteHeader__subMenuLink'
%li.siteHeader__subMenuItem= link_to "Organization Settings", organization_settings_path(organization), :class => 'siteHeader__subMenuLink' %li.siteHeader__subMenuItem= link_to "Domains", organization_domains_path(organization), :class => 'siteHeader__subMenuLink'
%li.siteHeader__subMenuItem= link_to "Manage Users", organization_users_path(organization), :class => 'siteHeader__subMenuLink' %li.siteHeader__subMenuItem= link_to "Organization Settings", organization_settings_path(organization), :class => 'siteHeader__subMenuLink'
- if current_user.admin? - if current_user.admin?
%li.siteHeader__subMenuItem= link_to "Create new organization", :new_organization, :class => 'siteHeader__subMenuLink' %li.siteHeader__subMenuItem= link_to "Create new organization", :new_organization, :class => 'siteHeader__subMenuLink'
- if current_user.organizations.present.count > 1 - if current_user.organizations.present.count > 1
%li.siteHeader__subMenuItem= link_to "Switch organization", root_path, :class => 'siteHeader__subMenuLink' %li.siteHeader__subMenuItem= link_to "Switch organization", root_path, :class => 'siteHeader__subMenuLink'
%li.siteHeader__navItem.siteHeader__navItem--user= current_user.name %li.siteHeader__navItem.siteHeader__navItem--user= current_user.name
%li.siteHeader__navItem= link_to "My Settings", settings_path, :class => 'sideHeader__navItemLink' %li.siteHeader__navItem= link_to "My Settings", settings_path, :class => 'sideHeader__navItemLink'
- if current_user.admin? && Postal.ip_pools? - if current_user.admin?
%li.siteHeader__navItem= link_to "IP Pools", ip_pools_path, :class => 'sideHeader__navItemLink' - if Postal.ip_pools?
%li.siteHeader__navItem= link_to "IP Pools", ip_pools_path, :class => 'sideHeader__navItemLink'
%li.siteHeader__navItem= link_to "Users", users_path, :class => 'sideHeader__navItemLink'
%li.siteHeader__navItem= link_to "Logout", logout_path, :method => :delete, :class => 'sideHeader__navItemLink' %li.siteHeader__navItem= link_to "Logout", logout_path, :method => :delete, :class => 'sideHeader__navItemLink'
.siteContent .siteContent

عرض الملف

@@ -1,11 +1,9 @@
- if organization.admin?(current_user) .navBar
.navBar %ul
%ul %li.navBar__item= link_to "Mail Servers", organization_root_path(organization), :class => ['navBar__link', active_nav == :servers ? 'is-active' : '']
%li.navBar__item= link_to "Mail Servers", organization_root_path(organization), :class => ['navBar__link', active_nav == :servers ? 'is-active' : ''] %li.navBar__item= link_to "Domains", organization_domains_path(organization), :class => ['navBar__link', active_nav == :domains ? 'is-active' : '']
%li.navBar__item= link_to "Domains", organization_domains_path(organization), :class => ['navBar__link', active_nav == :domains ? 'is-active' : ''] %li.navBar__item= link_to "Settings", organization_settings_path(organization), :class => ['navBar__link', active_nav == :settings ? 'is-active' : '']
%li.navBar__item= link_to "Settings", organization_settings_path(organization), :class => ['navBar__link', active_nav == :settings ? 'is-active' : ''] - if Postal.ip_pools?
- if Postal.ip_pools? %li.navBar__item= link_to "IPs", organization_ip_pools_path(organization), :class => ['navBar__link', active_nav == :ips ? 'is-active' : '']
%li.navBar__item= link_to "IPs", organization_ip_pools_path(organization), :class => ['navBar__link', active_nav == :ips ? 'is-active' : ''] - if current_user.admin?
%li.navBar__item= link_to "Users", organization_users_path(organization), :class => ['navBar__link', active_nav == :users ? 'is-active' : ''] %li.navBar__item= link_to "Delete Organization", organization_delete_path(organization), :class => ['navBar__link', active_nav == :delete ? 'is-active' : '']
- if organization.owner?(current_user)
%li.navBar__item= link_to "Delete Organization", organization_delete_path(organization), :class => ['navBar__link', active_nav == :delete ? 'is-active' : '']

عرض الملف

@@ -8,5 +8,4 @@
%li.navBar__item= link_to "IP Rules", [organization, @server, :ip_pool_rules], :class => ['navBar__link', active_nav == :ip_pool_rules ? 'is-active' : ''] %li.navBar__item= link_to "IP Rules", [organization, @server, :ip_pool_rules], :class => ['navBar__link', active_nav == :ip_pool_rules ? 'is-active' : '']
- if current_user.admin? - if current_user.admin?
%li.navBar__item= link_to "Advanced Settings", [:advanced, organization, @server], :class => ['navBar__link', active_nav == :admin ? 'is-active' : ''] %li.navBar__item= link_to "Advanced Settings", [:advanced, organization, @server], :class => ['navBar__link', active_nav == :admin ? 'is-active' : '']
- if organization.admin?(current_user) %li.navBar__item= link_to "Delete", [:delete, organization, @server], :class => ['navBar__link', active_nav == :delete ? 'is-active' : '']
%li.navBar__item= link_to "Delete", [:delete, organization, @server], :class => ['navBar__link', active_nav == :delete ? 'is-active' : '']

عرض الملف

@@ -13,5 +13,4 @@
%p.sidebarServerList__mode.label{:class => "label--serverStatus-#{server.status.underscore}"}= t("server_statuses.#{server.status.underscore}") %p.sidebarServerList__mode.label{:class => "label--serverStatus-#{server.status.underscore}"}= t("server_statuses.#{server.status.underscore}")
%p.sidebarServerList__title= server.name %p.sidebarServerList__title= server.name
%p.sidebarServerList__quantity #{number_with_precision server.message_rate, :precision => 2} messages/minute %p.sidebarServerList__quantity #{number_with_precision server.message_rate, :precision => 2} messages/minute
- if organization.admin?(current_user) %p.sidebar__new= link_to "Build a new mail server", [:new, organization, :server]
%p.sidebar__new= link_to "Build a new mail server", [:new, organization, :server]

عرض الملف

@@ -1,16 +0,0 @@
- page_title << "Join Organization"
.pageHeader
%h1.pageHeader__title
Join Organization
.pageContent.pageContent--compact
%h2.pageContent__intro.u-margin
Welcome to Postal.
- if @organizations.size == 1
You've been invited to join the <b>#{@organizations.first.name}</b> organization. Once accepted, you'll be able to
access this organization's mail servers.
- else
You've been invited to join an organization
%p.buttonSet
= link_to "Accept " + (@organizations.size == 1 ? "Invitation" : "Invitations"), '', :class => "button button--positive", :remote => true, :method => :post
= link_to "Reject " + (@organizations.size == 1 ? "Invitation" : "Invitations"), '', :class => "button button--danger", :remote => true, :method => :delete

عرض الملف

@@ -1,41 +0,0 @@
- @wide = true
- page_title << "Signup"
.subPageBox__title
Join the #{@user_invite.organizations.first.name} organization
= display_flash
.subPageBox__content
%p.subPageBox__text
If you don't already have an account on this system, you can create one below. Otherwise, you should
#{link_to "login to your existing account", login_path(:return_to => join_path(@user_invite.uuid)), :class => 'u-link'}
and add this organization to that.
.signupForm
= form_for @user, :url => signup_path do |f|
= hidden_field_tag 'return_to', params[:return_to]
= hidden_field_tag 'invite_token', params[:invite_token]
= f.error_messages
.fieldSet.fieldSet--compact.u-margin
.fieldSet__fieldPair
.fieldSet__field
= f.label :first_name, :class => 'fieldSet__label'
.fieldSet__input= f.text_field :first_name, :class => 'input input--text input--onWhite', :autofocus => true
.fieldSet__field
= f.label :last_name, :class => 'fieldSet__label'
.fieldSet__input= f.text_field :last_name, :class => 'input input--text input--onWhite'
.fieldSet__field
= f.label :email_address, :class => 'fieldSet__label'
.fieldSet__input= f.text_field :email_address, :class => 'input input--text input--onWhite'
.fieldSet__fieldPair
.fieldSet__field
= f.label :password, :class => 'fieldSet__label'
.fieldSet__input= f.password_field :password, :class => 'input input--text input--onWhite', :placeholder => '•••••••••••'
.fieldSet__field
= f.label :password_confirmation, "&nbsp;".html_safe, :class => 'fieldSet__label'
.fieldSet__input= f.password_field :password_confirmation, :class => 'input input--text input--onWhite', :placeholder => '•••••••••••'
.loginForm__submit
%ul.loginForm__links
%li= link_to "Back to login", login_path(:return_to => params[:return_to])
%p= submit_tag "Create Account", :class => 'button button--positive', :tabindex => 3

عرض الملف

@@ -1,18 +0,0 @@
- page_title << "Verify your e-mail address"
.pageHeader
%h1.pageHeader__title
Please verify your e-mail address
.pageContent.pageContent--compact
%h2.pageContent__intro.u-margin
We need to verify that you're the owner of the e-mail address on your account. It is currently <b>#{current_user.email_address}</b>. To
do this, we've sent you an e-mail with a 6-digit code. Please check your e-mail and enter the code within in the box below.
%p.pageContent__text
If you need to change your e-mail address, you can do this in from your #{link_to 'settings page', settings_path, :class => "u-link"}.
If you haven't received the e-mail, you can #{link_to 'click here to resend it', '', :class => "u-link"}.
= form_tag request.fullpath, :remote => true do
= hidden_field_tag 'return_to', params[:return_to]
%p.u-margin
= text_field_tag "code", params[:code], :autofocus => true, :class => 'input input--text js-multibox'
.buttonSet.u-center
= submit_tag "Verify my e-mail address", :class => 'button button--positive js-form-submit'

عرض الملف

@@ -1,24 +1,44 @@
= form_for @organization_user, :url => @organization_user.new_record? ? organization_users_path(organization) : organization_user_path(organization, @organization_user.user), :remote => true do |f| = form_for @user, :url => @user.new_record? ? users_path : user_path(@user), :remote => true do |f|
= f.error_messages = f.error_messages
= hidden_field_tag 'invite', params[:invite] .fieldSet
%fieldset.fieldSet .fieldSet__title
Enter user details
.fieldSet__field
= f.label :first_name, :class => 'fieldSet__label'
.fieldSet__input= f.text_field :first_name, :class => 'input input--text', :autofocus => true
.fieldSet__field
= f.label :last_name, :class => 'fieldSet__label'
.fieldSet__input= f.text_field :last_name, :class => 'input input--text'
.fieldSet__field .fieldSet__field
= f.label :email_address, :class => 'fieldSet__label' = f.label :email_address, :class => 'fieldSet__label'
.fieldSet__input .fieldSet__input= f.text_field :email_address, :class => 'input input--text', autocomplete: 'one-time-code'
= f.text_field :email_address, :autofocus => true, :class => 'input input--text', :disabled => @organization_user.persisted? - unless @user.persisted?
.fieldSet__field
= f.label :password, :class => 'fieldSet__label'
.fieldSet__input= f.password_field :password, :class => 'input input--text', :placeholder => '•••••••••••', autocomplete: 'one-time-code'
.fieldSet__field
= f.label :password_confirmation, "Confirm".html_safe, :class => 'fieldSet__label'
.fieldSet__input= f.password_field :password_confirmation, :class => 'input input--text', :placeholder => '•••••••••••', autocomplete: 'one-time-code'
%fieldset.fieldSet
.fieldSet__title .fieldSet__title
What level of access do you wish to grant? What level of access do you wish to grant?
.fieldSet__titleSubText
Admin users have full access to all organizations and settings. Non-admin users will only
have access to the organizations that you select here.
.fieldSet__field .fieldSet__field
= f.label :admin, :class => 'fieldSet__label' .fieldSet__label Admin?
.fieldSet__input .fieldSet__input
= f.select :admin, [["No - do not grant admin access", false], ["Yes - grant admin access", true]], {},:class => 'input input--select' = hidden_field_tag 'user[organization_ids][]'
%p.fieldSet__text = f.select :admin, [["Yes - grant admin access", true], ["No - do not grant admin access", false]], {},:class => 'input input--select fieldSet__checkboxListAfter js-checkbox-list-toggle'
Users who have admin access will be permitted to manage the organization as if they had the same %ul.checkboxList{:class => [@user.admin? ? 'is-hidden' : '']}
access as the organization owner. This includes managing users, creating & deleting mail servers, - for org in Organization.order(:name).to_a
and even removing the account. This level of access should granted carefully. %li.checkboxList__item
Regardless of which level you select, this user will have access to all servers within the organization. .checkboxList__checkbox= check_box_tag "user[organization_ids][]", org.id, @user.organizations.include?(org), :id => "org_#{org.id}"
.checkboxList__label
= label_tag "org_#{org.id}", org.name, :class => 'checkboxList__actualLabel'
.fieldSetSubmit.buttonSet .fieldSetSubmit.buttonSet
= submit_tag @organization_user.new_record? ? "Add User" : "Save User", :class => 'button button--positive js-form-submit' = submit_tag @user.new_record? ? "Add User" : "Save User", :class => 'button button--positive js-form-submit'
.fieldSetSubmit__delete .fieldSetSubmit__delete
= link_to "Back to user list", [organization, :users], :class => 'button button--neutral' = link_to "Back to user list", :users, :class => 'button button--neutral'

عرض الملف

@@ -3,13 +3,10 @@
.pageHeader .pageHeader
%h1.pageHeader__title %h1.pageHeader__title
%span.pageHeader__titlePrevious %span.pageHeader__titlePrevious
= @organization.name = link_to 'Users', users_path
&rarr;
Users
&rarr; &rarr;
Edit user permissions Edit user permissions
= render 'organizations/nav', :active_nav => :users
.pageContent.pageContent--compact .pageContent.pageContent--compact
= render 'form' = render 'form'

عرض الملف

@@ -1,57 +1,21 @@
- page_title << "Users" - page_title << "Users"
.pageHeader .pageHeader
%h1.pageHeader__title %h1.pageHeader__title
%span.pageHeader__titlePrevious
= @organization.name
&rarr;
Users Users
= render 'organizations/nav', :active_nav => :users
.pageContent.pageContent--compact .pageContent.pageContent--compact
- if @users.empty? && @pending_users.empty? %ul.userList.u-margin
.noData.noData--clean - for user in @users
%p.noData__title There are no users assigned to this organization. %li.userList__item
%p.noData__text = image_tag user.avatar_url, :class => 'userList__avatar'
You add additional users that will be permitted to access this organization. .userList__details
They will be sent an email and they'll be able to create an account which will %p.userList__name
allow them to login and access this organization. = user.name
%p.noData__button.buttonSet.buttonSet--center - if user.admin?
= link_to "Invite the first user", [:new, organization, :user], :class => 'button button--positive' %span.userList__admin.label Admin
%p.userList__email= user.email_address
%ul.userList__actions
%li= link_to "Edit permissions", [:edit, user]
%li= link_to "Delete user", user, :method => :delete, :data => {:confirm => "Are you sure you wish to revoke #{user.name}'s access?", :disable_with => "Deleting..."}, :remote => true, :class => 'userList__revoke'
- else %p.u-center= link_to "Add a new user", :new_user, :class => 'button button--positive'
%p.pageContent__intro.u-margin
You can share access to this organization with other people by adding them
here. They'll need to create their own account first and then you'll be able
to add them to your organization by entering their e-mail address.
%ul.userList.u-margin
- for user in @users
%li.userList__item
= image_tag user.user.avatar_url, :class => 'userList__avatar'
.userList__details
%p.userList__name
= user.user.name
- if user.user == organization.owner
%span.userList__owner.label Owner
- elsif user.admin?
%span.userList__admin.label Admin
%p.userList__email= user.user.email_address
%ul.userList__actions
- if organization.owner != user.user
%li= link_to "Edit permissions", [:edit, organization, user.user]
- if organization.owner == current_user
%li= link_to "Make owner", [:make_owner, organization, user.user], :method => :post, :data => {:confirm => "Are you sure you wish to make #{user.user.name} the owner of this organization? They will be granted full admin access. You won't be able to change this back.", :disable_with => "Promoting..."}, :remote => true
%li= link_to "Revoke access", [organization, user.user], :method => :delete, :data => {:confirm => "Are you sure you wish to revoke #{user.user.name}'s access to the organization?", :disable_with => "Deleting..."}, :remote => true, :class => 'userList__revoke'
- for user in @pending_users
%li.userList__item
= image_tag user.user.avatar_url, :class => 'userList__avatar'
.userList__details
%p.userList__name
= user.user.email_address
%span.userList__pending.label Pending
%ul.userList__actions
%li= link_to "Edit permissions", edit_organization_user_path(organization, user.user, :invite => 1)
%li= link_to "Cancel invitation", organization_user_path(organization, user.user, :invite => 1), :method => :delete, :data => {:confirm => "Are you sure you wish to cancel this invitation?", :disable_with => "Deleting..."}, :remote => true, :class => 'userList__revoke'
%p.u-center= link_to "Invite a new user", [:new, organization, :user], :class => 'button button--positive'

عرض الملف

@@ -3,17 +3,14 @@
.pageHeader .pageHeader
%h1.pageHeader__title %h1.pageHeader__title
%span.pageHeader__titlePrevious %span.pageHeader__titlePrevious
= @organization.name = link_to 'Users', :users
&rarr;
Users
&rarr; &rarr;
Add user Add user
= render 'organizations/nav', :active_nav => :users
.pageContent.pageContent--compact .pageContent.pageContent--compact
%p.pageContent__intro.u-margin %p.pageContent__intro.u-margin
To add someone to your organization enter their e-mail address below. If To add someone to this Postal installation, you can add them below. You'll need to
they don't already have a Postal account, they'll need to create one choose whether to make them an admin (full access to all organizations and settings)
before you can add them to your account. or whether you wish to limit them to specific organizations.
= render 'form' = render 'form'

عرض الملف

@@ -14,9 +14,6 @@ Bundler.require(*Rails.groups)
module Postal module Postal
class Application < Rails::Application class Application < Rails::Application
# Set the Rails logger
config.logger = Postal.logger_for(:rails)
# Disable most generators # Disable most generators
config.generators do |g| config.generators do |g|
g.orm :active_record g.orm :active_record

عرض الملف

@@ -56,9 +56,7 @@ Rails.application.routes.draw do
post :suspend, :on => :member post :suspend, :on => :member
post :unsuspend, :on => :member post :unsuspend, :on => :member
end end
resources :users do
post :make_owner, :on => :member
end
resources :ip_pool_rules resources :ip_pool_rules
resources :ip_pools, :controller => 'organization_ip_pools' do resources :ip_pools, :controller => 'organization_ip_pools' do
put :assignments, :on => :collection put :assignments, :on => :collection
@@ -71,6 +69,7 @@ Rails.application.routes.draw do
end end
resources :organizations, :except => [:index] resources :organizations, :except => [:index]
resources :users
resources :ip_pools do resources :ip_pools do
resources :ip_addresses resources :ip_addresses
end end
@@ -79,16 +78,15 @@ Rails.application.routes.draw do
patch 'settings' => 'user#update' patch 'settings' => 'user#update'
post 'persist' => 'sessions#persist' post 'persist' => 'sessions#persist'
match 'verify' => 'user#verify', :via => [:get, :post]
get 'signup/:invite_token' => 'user#new', :as => 'new_signup'
post 'signup' => 'user#create'
match 'join/:token' => 'user#join', :via => [:get, :post, :delete], :as => 'join'
get 'login' => 'sessions#new' get 'login' => 'sessions#new'
post 'login' => 'sessions#create' post 'login' => 'sessions#create'
get 'login/token' => 'sessions#create_with_token' get 'login/token' => 'sessions#create_with_token'
delete 'logout' => 'sessions#destroy' delete 'logout' => 'sessions#destroy'
match 'login/reset' => 'sessions#begin_password_reset', :via => [:get, :post] match 'login/reset' => 'sessions#begin_password_reset', :via => [:get, :post]
match 'login/reset/:token' => 'sessions#finish_password_reset', :via => [:get, :post] match 'login/reset/:token' => 'sessions#finish_password_reset', :via => [:get, :post]
root 'organizations#index'
get 'ip' => 'sessions#ip' get 'ip' => 'sessions#ip'
root 'organizations#index'
end end