aboutsummaryrefslogtreecommitdiff
path: root/src/actions/mixins/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/actions/mixins/api')
-rw-r--r--src/actions/mixins/api/auth/helpers.cr28
-rw-r--r--src/actions/mixins/api/auth/require_auth_token.cr34
-rw-r--r--src/actions/mixins/api/auth/skip_require_auth_token.cr10
3 files changed, 72 insertions, 0 deletions
diff --git a/src/actions/mixins/api/auth/helpers.cr b/src/actions/mixins/api/auth/helpers.cr
new file mode 100644
index 0000000..6b51cb5
--- /dev/null
+++ b/src/actions/mixins/api/auth/helpers.cr
@@ -0,0 +1,28 @@
+module Api::Auth::Helpers
+ # The 'memoize' macro makes sure only one query is issued to find the user
+ memoize def current_user? : User?
+ auth_token.try do |value|
+ user_from_auth_token(value)
+ end
+ end
+
+ private def auth_token : String?
+ bearer_token || token_param
+ end
+
+ private def bearer_token : String?
+ context.request.headers["Authorization"]?
+ .try(&.gsub("Bearer", ""))
+ .try(&.strip)
+ end
+
+ private def token_param : String?
+ params.get?(:auth_token)
+ end
+
+ private def user_from_auth_token(token : String) : User?
+ UserToken.decode_user_id(token).try do |user_id|
+ UserQuery.new.id(user_id).first?
+ end
+ end
+end
diff --git a/src/actions/mixins/api/auth/require_auth_token.cr b/src/actions/mixins/api/auth/require_auth_token.cr
new file mode 100644
index 0000000..e018638
--- /dev/null
+++ b/src/actions/mixins/api/auth/require_auth_token.cr
@@ -0,0 +1,34 @@
+module Api::Auth::RequireAuthToken
+ macro included
+ before require_auth_token
+ end
+
+ private def require_auth_token
+ if current_user?
+ continue
+ else
+ json auth_error_json, 401
+ end
+ end
+
+ private def auth_error_json
+ ErrorSerializer.new(
+ message: "Not authenticated.",
+ details: auth_error_details
+ )
+ end
+
+ private def auth_error_details : String
+ if auth_token
+ "The provided authentication token was incorrect."
+ else
+ "An authentication token is required. Please include a token in an 'auth_token' param or 'Authorization' header."
+ end
+ end
+
+ # Tells the compiler that the current_user is not nil since we have checked
+ # that the user is signed in
+ private def current_user : User
+ current_user?.as(User)
+ end
+end
diff --git a/src/actions/mixins/api/auth/skip_require_auth_token.cr b/src/actions/mixins/api/auth/skip_require_auth_token.cr
new file mode 100644
index 0000000..68098cf
--- /dev/null
+++ b/src/actions/mixins/api/auth/skip_require_auth_token.cr
@@ -0,0 +1,10 @@
+module Api::Auth::SkipRequireAuthToken
+ macro included
+ skip require_auth_token
+ end
+
+ # Since sign in is not required, current_user might be nil
+ def current_user : User?
+ current_user?
+ end
+end