Further API implmentation.

This commit is contained in:
Jonathan Bernard 2015-03-02 21:26:06 -06:00
parent dc5cb78320
commit 43ba9216e5
5 changed files with 207 additions and 21 deletions

View File

@ -80,6 +80,10 @@ public class NLSongsDB {
'UPDATE services SET "date" = ?, service_type = ? WHERE id = ?',
[sdf.format(service.date), service.serviceType, service.id] ) }
public int delete(Service service) {
sql.execute("DELETE FROM services WHERE id = ?", [service.id])
return sql.updateCount }
/// ### Songs
public Song findSong(int id) {
def row = sql.firstRow("SELECT * FROM songs WHERE id = ?", [id])
@ -126,6 +130,10 @@ public class NLSongsDB {
"UPDATE songs SET name = ?, artists = ? WHERE id = ?",
[song.name, wrapArtists(song.artists), song.id] ) }
public int delete(Song song) {
sql.execute("DELETE FROM songs WHERE id = ?", [song.id])
return sql.updateCount }
/// ### Performances
public Performance findPerformance(int serviceId, int songId) {
def perf = sql.firstRow(
@ -162,34 +170,92 @@ public class NLSongsDB {
public int delete(Performance perf) {
sql.execute(
"DELETE FROM performances WHERE service_id = ? AND song_id = ?")
return sql.getUpdateCount() }
"DELETE FROM performances WHERE service_id = ? AND song_id = ?",
[perf.service_id, perf.song_id] )
return sql.updateCount }
/// ### API Keys
public ApiKey findKey(String key) {
def row = sql.firstRow("SELECT * FROM api_keys WHERE key = ?", [key])
return recordToModel(row, ApiKey) }
/// ### Users
public List<User> findAllUsers() {
return sql.rows("SELECT * FROM users").
collect { buildUser(it); } }
public User findUser(String username) {
def row = sql.firstRow("SELECT * FROM users WHERE username = ?",
[username])
return buildUser(row) }
public ApiKey save(ApiKey apiKey) {
if (findKey(apiKey.key)) {
update(apiKey)
return apiKey }
else return create(apiKey) }
public User save(User user) {
if (findUser(user.username)) {
update(user); return user }
else return create(user) }
public ApiKey create(ApiKey apiKey) {
sql.executeInsert(
"INSERT INTO api_keys (key, description) VALUES (?, ?)",
[apiKey.key, apiKey.description] )
public User create(User user) {
int newId = sql.executeInsert(
"INSERT INTO users (username, pwd, role) VALUES (?, ?, ?)",
[user.username, user.pwd, user.role])[0][0]
return apiKey }
user.id = newId
return user }
public int update(ApiKey apiKey) {
public int update(User user) {
return sql.executeUpdate(
"UPDATE api_keys SET description = ? WHERE key = ?",
[apiKey.description, apiKey.key]) }
"UPDATE user SET username = ?, pwd = ?, role = ? WHERE id = ?",
[user.username, user.pwd, user.role, user.id]) }
/// ### User management
// TODO
public int delete(User user) {
sql.execute("DELETE FROM users WHERE username = ?")
return sql.updateCount }
private static User buildUser(def row) {
User user = new User(username: row["username"], role: row["role"])
user.@pwd = row["pwd"]
return user; }
/// ### Tokens
public Token findToken(String token) {
def row = sql.firstRow("""\
SELECT t.*, u.*
FROM
tokens t JOIN
users u ON
t.user_id = u.id
WHERE t.token = ?""", [token])
return buildToken(row) }
public Token renewToken(Token token) {
def foundToken = findToken(token.token);
// If the token has expired we will not renew it.
if (new Date() > token.expires) return null;
// Otherwise, renew and return the new values.
assert sql.executeUpdate("UPDATE tokens SET " +
"expires = current_timestamp + interval '1 day' WHEREtoken = ?",
[token.token]) == 1
def updatedToken = findToken(token.token);
token.expires = updatedToken.expires;
return token; }
public Token save(Token token) {
if (findToken(token.token)) {
update(token); return token }
else return create(token) }
public Token create(Token token) {
sql.executeInsert("INSERT INTO tokens VALUES (?, ?, ?)",
[token.token, token.user.id, token.expires])
return Token }
public int update(Token token) {
return sql.executeUpdate(
"UPDATE tokens SET expires = ? WHERE token = ?",
[token.expires, token.token]) }
public int delete(Token token) {
sql.execute("DELETE FROM tokens WHERE token = ?", [token.token])
return sql.updateCount }
/// ### Utility functions
static def recordToModel(def record, Class clazz) {
@ -224,6 +290,12 @@ public class NLSongsDB {
record[recordKey] = v }
return record }
private static Token buildToken(def row) {
User user = buildUser(row)
return new Token(
token: row["token"], user: user, expires: row["expires"]) }
public static List<String> unwrapArtists(String artists) {
return artists.split(';') as List<String> }

View File

@ -0,0 +1,12 @@
package com.jdbernard.nlsongs.rest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
@Path("v1/ping") @AllowCors
public class PingResource {
@GET
@Produces("text/plain")
public String ping() { return "pong"; } }

View File

@ -2,6 +2,7 @@ package com.jdbernard.nlsongs.rest;
import java.util.Date;
import java.util.List;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
@ -38,6 +39,14 @@ public class ServicesResource {
NLSongsContext.songsDB.update(service);
return service; }
@DELETE @Path("/{serviceId}")
public Service deleteService(@PathParam("serviceId") int serviceId) {
Service service = NLSongsContext.songsDB.findService(serviceId);
if (service != null) { NLSongsContext.songsDB.delete(service); }
return service; }
@GET @Path("/withSong/{songId}")
public List<Service> getServicesForSong(@PathParam("songId") int songId) {
return NLSongsContext.songsDB.findServicesForSongId(songId); }

View File

@ -1,6 +1,7 @@
package com.jdbernard.nlsongs.rest;
import java.util.List;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
@ -36,6 +37,14 @@ public class SongsResource {
NLSongsContext.songsDB.update(song);
return song; }
@DELETE @Path("/{songId}")
public Song deleteSong(@PathParam("songId") int songId) {
Song song = NLSongsContext.songsDB.findSong(songId);
if (song != null) { NLSongsContext.songsDB.delete(song); }
return song; }
@GET @Path("/forService/{serviceId}")
public List<Song> getSongsForService(@PathParam("serviceId") int serviceId) {
return NLSongsContext.songsDB.findSongsForServiceId(serviceId); }
@ -43,4 +52,5 @@ public class SongsResource {
@GET @Path("/byArtist/{artist}")
public List<Song> getSongsForArtist(@PathParam("artist") String artist) {
return NLSongsContext.songsDB.findSongsByArtist(artist); }
}

View File

@ -0,0 +1,83 @@
package com.jdbernard.nlsongs.rest;
import java.util.Date;
import java.util.List;
import javax.annotation.security.RolesAllowed;
import javax.annotation.security.PermitAll;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Consumes;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import com.jdbernard.nlsongs.servlet.NLSongsContext;
import com.jdbernard.nlsongs.model.User;
import com.jdbernard.nlsongs.model.Token;
@Path("v1/users") @AllowCors @PermitAll
@Produces({MediaType.APPLICATION_JSON})
@Consumes({MediaType.APPLICATION_JSON})
public class UsersResource {
@Context SecurityContext secCtx;
@GET @RolesAllowed("admin")
public List<User> getUsers() {
return NLSongsContext.songsDB.findAllUsers(); }
@POST @RolesAllowed("admin")
public User postUser(User user) {
return NLSongsContext.songsDB.create(user); }
@GET @Path("/{username}")
public Response getUser(@PathParam("username") String username) {
// If they are looking up their own information, OK.
if (username == secCtx.getUserPrincipal().getName() ||
// Or if they are an admin, OK.
secCtx.isUserInRole("admin")) {
return Response.ok(
NLSongsContext.songsDB.findUser(username)).build(); }
else return Response.status(Response.Status.FORBIDDEN).build(); }
@PUT @Path("/{username}")
public Response putUser(@PathParam("username") String username, User user) {
// If they are looking up their own information, OK.
if (username == secCtx.getUserPrincipal().getName() ||
// Or if they are an admin, OK.
secCtx.isUserInRole("admin")) {
NLSongsContext.songsDB.update(user);
return Response.ok(user).build(); }
else return Response.status(Response.Status.FORBIDDEN).build(); }
@DELETE @Path("/{username}")
public Response deleteUser(@PathParam("username") String username) {
// If they are looking up their own information, OK.
if (username == secCtx.getUserPrincipal().getName() ||
// Or if they are an admin, OK.
secCtx.isUserInRole("admin")) {
User user = NLSongsContext.songsDB.findUser(username);
if (user != null) NLSongsContext.songsDB.delete(user);
return Response.ok(user).build(); }
else return Response.status(Response.Status.FORBIDDEN).build(); }
}