Class: AgentCode::AuthController
- Inherits:
-
ActionController::API
- Object
- ActionController::API
- AgentCode::AuthController
- Defined in:
- lib/agentcode/controllers/auth_controller.rb
Overview
Authentication controller — mirrors Laravel AuthController exactly.
Endpoints: POST /api/auth/login POST /api/auth/logout POST /api/auth/password/recover POST /api/auth/password/reset POST /api/auth/register
Instance Method Summary collapse
-
#login ⇒ Object
POST /api/auth/login.
-
#logout ⇒ Object
POST /api/auth/logout.
-
#recover_password ⇒ Object
POST /api/auth/password/recover.
-
#register_with_invitation ⇒ Object
POST /api/auth/register.
-
#reset ⇒ Object
POST /api/auth/password/reset.
Instance Method Details
#login ⇒ Object
POST /api/auth/login
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/agentcode/controllers/auth_controller.rb', line 16 def login email = params[:email].to_s.strip password = params[:password].to_s if email.blank? || password.blank? return render json: { message: "Invalid credentials" }, status: :unauthorized end user_class = "User".safe_constantize return render json: { message: "Invalid credentials" }, status: :unauthorized unless user_class user = user_class.find_by(email: email) unless user&.authenticate(password) return render json: { message: "Invalid credentials" }, status: :unauthorized end token = generate_api_token(user) # Get the first organization the user belongs to organization_slug = nil if user.respond_to?(:organizations) first_org = user.organizations.first organization_slug = first_org&.slug end render json: { token: token, organization_slug: organization_slug }, status: :ok end |
#logout ⇒ Object
POST /api/auth/logout
49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/agentcode/controllers/auth_controller.rb', line 49 def logout user = current_user if user.respond_to?(:regenerate_api_token) user.regenerate_api_token elsif user.respond_to?(:update_column) && user.class.column_names.include?("api_token") user.update_column(:api_token, SecureRandom.hex(32)) end render json: { message: "Logged out successfully" }, status: :ok end |
#recover_password ⇒ Object
POST /api/auth/password/recover
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/agentcode/controllers/auth_controller.rb', line 62 def recover_password email = params[:email].to_s.strip if email.blank? return render json: { errors: { email: ["The email field is required."] } }, status: :unprocessable_entity end user_class = "User".safe_constantize user = user_class&.find_by(email: email) if user token = SecureRandom.hex(32) # Store reset token if user.respond_to?(:update_columns) user.update_columns( reset_password_token: token, reset_password_sent_at: Time.current ) end # Send email via mailer if available mailer_class = "AgentCode::PasswordRecoveryMailer".safe_constantize mailer_class&.recover(user, token)&.deliver_later end # Always return success to prevent email enumeration render json: { message: "Password recovery email sent." }, status: :ok end |
#register_with_invitation ⇒ Object
POST /api/auth/register
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/agentcode/controllers/auth_controller.rb', line 139 def register_with_invitation errors = {} errors[:token] = ["The token field is required."] if params[:token].blank? errors[:name] = ["The name field is required."] if params[:name].blank? errors[:email] = ["The email field is required."] if params[:email].blank? errors[:password] = ["The password field is required."] if params[:password].blank? if params[:password].present? && params[:password].length < 8 errors[:password] = ["The password must be at least 8 characters."] end if params[:password].present? && params[:password] != params[:password_confirmation] errors[:password_confirmation] = ["The password confirmation does not match."] end user_class = "User".safe_constantize if user_class && params[:email].present? && user_class.exists?(email: params[:email]) errors[:email] = ["The email has already been taken."] end unless errors.empty? return render json: { errors: errors }, status: :unprocessable_entity end # Find invitation invitation = OrganizationInvitation.find_by(token: params[:token], status: "pending") unless invitation return render json: { message: "Invalid or expired invitation token" }, status: :not_found end if invitation.expired? invitation.update!(status: "expired") return render json: { message: "This invitation has expired" }, status: :unprocessable_entity end # Validate email matches invitation unless invitation.email == params[:email] return render json: { message: "Email does not match the invitation" }, status: :unprocessable_entity end # Create user user = user_class.create!( name: params[:name], email: params[:email], password: params[:password] ) # Accept invitation (adds user to organization) invitation.accept!(user) # Generate token token = generate_api_token(user) # Get organization slug for redirect organization = invitation.organization organization_slug = organization&.slug render json: { message: "Registration successful", token: token, user: user.as_json(except: %w[password_digest api_token reset_password_token]), organization_slug: organization_slug }, status: :created end |
#reset ⇒ Object
POST /api/auth/password/reset
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/agentcode/controllers/auth_controller.rb', line 93 def reset errors = {} errors[:token] = ["The token field is required."] if params[:token].blank? errors[:email] = ["The email field is required."] if params[:email].blank? errors[:password] = ["The password field is required."] if params[:password].blank? if params[:password].present? && params[:password].length < 8 errors[:password] = ["The password must be at least 8 characters."] end if params[:password].present? && params[:password] != params[:password_confirmation] errors[:password_confirmation] = ["The password confirmation does not match."] end unless errors.empty? return render json: { errors: errors }, status: :unprocessable_entity end user_class = "User".safe_constantize user = user_class&.find_by(email: params[:email]) unless user return render json: { message: "Token is invalid or expired." }, status: :bad_request end # Verify token valid_token = user.respond_to?(:reset_password_token) && user.reset_password_token == params[:token] && user.respond_to?(:reset_password_sent_at) && user.reset_password_sent_at.present? && user.reset_password_sent_at > 1.hour.ago unless valid_token return render json: { message: "Token is invalid or expired." }, status: :bad_request end # Update password user.password = params[:password] user.reset_password_token = nil user.reset_password_sent_at = nil user.save! render json: { message: "Password has been reset." }, status: :ok end |