Skip to content

Add type restrictions to Oauth directory #15687

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

Vici37
Copy link
Contributor

@Vici37 Vici37 commented Apr 20, 2025

This is the output of compiling cr-source-typer and running it with the below incantation:

CRYSTAL_PATH="./src" ./typer spec/std_spec.cr --error-trace --exclude src/crystal/ --stats --progress --union-size-threshold 2 --ignore-private-defs src/oauth

This is related to #15682 .

@@ -6,7 +6,7 @@ struct OAuth::AuthorizationHeader
@first = true
end

def add(key, value)
def add(key : String, value : String?) : Bool?
Copy link
Member

@straight-shoota straight-shoota Apr 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: The return type Bool? is technically correct. But it doesn't make sense.

Bool is inferred from the last expression. It just accidentally leaks an irrelevant internal detail. The return type should be only Nil.

Suggested change
def add(key : String, value : String?) : Bool?
def add(key : String, value : String?) : Nil

@@ -2,7 +2,7 @@
#
# Use `#authenticate` to authenticate an `HTTP::Client`.
abstract class OAuth2::AccessToken
def self.new(pull : JSON::PullParser)
def self.new(pull : JSON::PullParser) : OAuth2::AccessToken
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Use self to designate this method as a constructor.

Suggested change
def self.new(pull : JSON::PullParser) : OAuth2::AccessToken
def self.new(pull : JSON::PullParser) : self

Technically, this is might not even be necessary because the method name .new implies a constructor. But it's still best to follow the expected type annotation scheme for constructors.

Ditto below.

@@ -34,7 +34,7 @@ class OAuth2::AccessToken::Mac < OAuth2::AccessToken
request.headers["Authorization"] = header
end

def self.signature(ts, nonce, method, uri, host, port, ext, mac_algorithm, mac_key) : String
def self.signature(ts : Int64 | Int32, nonce : String, method : String, uri : String, host : String, port : Int32 | String, ext : String, mac_algorithm : String, mac_key : String) : String
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Unions between numeric types should almost always be resolved to either an abstract type like Int or the biggest possible type (to make use of autocasting).

ts is a unix timestamp, so in theory it should probably be UInt64.
But that won't autocast from any signed integer type.

Maybe Int is best then... or leave it unrestrictected?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only see ts used for its string construction of the normalized_request_string, so unrestricted makes sense, too. I didn't realize ts stood for timestamp, ha. I can remove the restriction on that argument for now.

@Vici37 Vici37 force-pushed the add-type-restrictions-to-oauth branch from 110f338 to 674981b Compare April 23, 2025 04:16
@straight-shoota
Copy link
Member

@Vici37 Please avoid force-pushes on PRs with active review, in order to preserve history and make the reviewer's jobs easier (cf. https://github.com/crystal-lang/crystal/blob/master/CONTRIBUTING.md#making-good-pull-requests).

That means, no rebasing. Just keep old commits around and push new ones (which can include merges with master).

@Vici37
Copy link
Contributor Author

Vici37 commented Apr 24, 2025

Whoops! Yup, my mistake, sorry about that. Happy to have learned that lesson through a relatively small PR 😅

@@ -72,7 +72,7 @@ class OAuth::Consumer
# [RFC 5849, Section 2.1](https://tools.ietf.org/html/rfc5849#section-2.1).
#
# Raises `OAuth::Error` if there was an error getting the request token.
def get_request_token(oauth_callback = "oob") # : RequestToken
def get_request_token(oauth_callback : String = "oob") : OAuth::RequestToken
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Full path is not needed.

Suggested change
def get_request_token(oauth_callback : String = "oob") : OAuth::RequestToken
def get_request_token(oauth_callback : String = "oob") : RequestToken

@@ -81,7 +81,7 @@ class OAuth::Consumer
# Returns an authorize URI from a given request token to redirect the user
# to obtain an access token, as specified by
# [RFC 5849, Section 2.2](https://tools.ietf.org/html/rfc5849#section-2.2).
def get_authorize_uri(request_token, oauth_callback = nil) : String
def get_authorize_uri(request_token : OAuth::RequestToken, oauth_callback : String? = nil) : String
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Suggested change
def get_authorize_uri(request_token : OAuth::RequestToken, oauth_callback : String? = nil) : String
def get_authorize_uri(request_token : RequestToken, oauth_callback : String? = nil) : String

@@ -116,7 +116,7 @@ class OAuth::Consumer
# [RFC 5849, Section 2.3](https://tools.ietf.org/html/rfc5849#section-2.3).
#
# Raises `OAuth::Error` if there was an error getting the access token.
def get_access_token(request_token, oauth_verifier, extra_params = nil) : AccessToken
def get_access_token(request_token : OAuth::RequestToken, oauth_verifier : String, extra_params : Hash(String, String)? = nil) : AccessToken
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Suggested change
def get_access_token(request_token : OAuth::RequestToken, oauth_verifier : String, extra_params : Hash(String, String)? = nil) : AccessToken
def get_access_token(request_token : RequestToken, oauth_verifier : String, extra_params : Hash(String, String)? = nil) : AccessToken

@@ -34,7 +34,7 @@ class OAuth2::AccessToken::Mac < OAuth2::AccessToken
request.headers["Authorization"] = header
end

def self.signature(ts, nonce, method, uri, host, port, ext, mac_algorithm, mac_key) : String
def self.signature(ts, nonce : String, method : String, uri : String, host : String, port : Int32 | String, ext : String, mac_algorithm : String, mac_key : String) : String
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

String restriction for port seems a bit odd...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ha, agreed, good catch. Looks to be caused by this spec that's passing in "4000" for the port

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants