Skip to content

Commit

Permalink
Add new endpoint - List Emails (#902)
Browse files Browse the repository at this point in the history
* Add new endpoint - List Emails

* Adding problem filter
  • Loading branch information
john-joe-givery authored Feb 6, 2024
1 parent 59bfe4e commit ecbab9e
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 1 deletion.
3 changes: 2 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ lazy val github4s = (crossProject(JSPlatform, JVMPlatform))
Test / scalacOptions -= "-Wnonunit-statement",
mimaPreviousArtifacts := Set("com.47deg" %% "github4s" % "0.32.1"),
mimaBinaryIssueFilters ++= Seq(
ProblemFilters.exclude[IncompatibleMethTypeProblem]("github4s.http.HttpClient.this")
ProblemFilters.exclude[IncompatibleMethTypeProblem]("github4s.http.HttpClient.this"),
ProblemFilters.exclude[ReversedMissingMethodProblem]("github4s.algebras.Users.getEmails")
)
)

Expand Down
2 changes: 2 additions & 0 deletions github4s/shared/src/main/scala/github4s/Decoders.scala
Original file line number Diff line number Diff line change
Expand Up @@ -424,4 +424,6 @@ object Decoders {
deriveDecoder[SearchCodeResult]
implicit val decodeSearchCodeResultItem: Decoder[SearchCodeResultItem] =
deriveDecoder[SearchCodeResultItem]

implicit val decoderEmail: Decoder[Email] = deriveDecoder[Email]
}
2 changes: 2 additions & 0 deletions github4s/shared/src/main/scala/github4s/Encoders.scala
Original file line number Diff line number Diff line change
Expand Up @@ -293,4 +293,6 @@ object Encoders {
deriveEncoder[SearchCodeResult]
implicit val encodeSearchCodeResultItem: Encoder[SearchCodeResultItem] =
deriveEncoder[SearchCodeResultItem]

implicit val encoderEmail: Encoder[Email] = deriveEncoder[Email]
}
12 changes: 12 additions & 0 deletions github4s/shared/src/main/scala/github4s/algebras/Users.scala
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,16 @@ trait Users[F[_]] {
pagination: Option[Pagination] = None,
headers: Map[String, String] = Map()
): F[GHResponse[List[User]]]

/**
* Get information for an authenticated user's associated email addresses
*
* @param pagination Limit and Offset for pagination
* @param headers optional user headers to include in the request
* @return GHResponse[Email] Email details
*/
def getEmails(
pagination: Option[Pagination] = None,
headers: Map[String, String] = Map()
): F[GHResponse[List[Email]]]
}
24 changes: 24 additions & 0 deletions github4s/shared/src/main/scala/github4s/domain/Email.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2016-2023 47 Degrees Open Source <https://www.47deg.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package github4s.domain

final case class Email(
email: String,
primary: Boolean,
verified: Boolean,
visibility: Option[String]
)
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,11 @@ class UsersInterpreter[F[_]](implicit client: HttpClient[F]) extends Users[F] {
): F[GHResponse[List[User]]] =
client
.get[List[User]](s"users/$username/following", headers, pagination = pagination)

override def getEmails(
pagination: Option[Pagination],
headers: Map[String, String]
): F[GHResponse[List[Email]]] =
client
.get[List[Email]]("user/emails", headers, pagination = pagination)
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,14 @@ trait UsersSpec extends BaseIntegrationSpec {
response.statusCode shouldBe notFoundStatusCode
}

"Users >> GetEmails" should "return error on Left when no accessToken is provided" taggedAs Integration in {
val response =
clientResource
.use(client => GithubClient[IO](client).users.getEmails(None, headerUserAgent))
.unsafeRunSync()

testIsLeft[GHError.UnauthorizedError, List[Email]](response)
response.statusCode shouldBe unauthorizedStatusCode
}

}
11 changes: 11 additions & 0 deletions github4s/shared/src/test/scala/github4s/unit/UserSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,15 @@ class UserSpec extends BaseSpec {
users.getFollowing(validUsername, None, headerUserAgent).shouldNotFail
}

"User.getEmails" should "call to httpClient.get with the right parameters" in {

implicit val httpClientMock: HttpClient[IO] = httpClientMockGet[List[Email]](
url = s"user/emails",
response = IO.pure(List(email))
)

val users = new UsersInterpreter[IO]
users.getEmails(None, headerUserAgent).shouldNotFail
}

}
3 changes: 3 additions & 0 deletions github4s/shared/src/test/scala/github4s/utils/TestData.scala
Original file line number Diff line number Diff line change
Expand Up @@ -637,4 +637,7 @@ trait TestData {

val validReviewers: ReviewersRequest =
ReviewersRequest(List(validUsername), List(validSlug))

val email: Email =
Email("[email protected]", primary = true, verified = true, Some("public"))
}
19 changes: 19 additions & 0 deletions microsite/docs/user.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,23 @@ The `result` on the right is the corresponding [List[User]][user-scala].

See [the API doc](https://developer.github.com/v3/users/followers/#list-users-followed-by-another-use) for full reference.

### List email addresses for the authenticated user

You can get a list of emails associated with the authenticated user using `getEmails`, it takes as argument:

- `pagination`: Limit and Offset for pagination, optional.

```scala mdoc:compile-only
val getEmails = gh.users.getEmails()
getEmails.flatMap(_.result match {
case Left(e) => IO.println(s"Something went wrong: ${e.getMessage}")
case Right(r) => IO.println(r)
})
```

The `result` on the right is the corresponding [List[Email]][email-scala].

See [the API doc](https://developer.github.com/v3/users/emails/#list-email-addresses-for-the-authenticated-user) for full reference.

[user-scala]: https://github.com/47degrees/github4s/blob/main/github4s/shared/src/main/scala/github4s/domain/User.scala
[email-scala]: https://github.com/47degrees/github4s/blob/main/github4s/shared/src/main/scala/github4s/domain/Email.scala

0 comments on commit ecbab9e

Please sign in to comment.