separated ticket object from permission object to facilitate re-use of permission object with tokens

pull/708/merge
Justin Richer 2015-03-17 21:16:29 -04:00
parent f123366069
commit 1be9da52c6
10 changed files with 203 additions and 119 deletions

View File

@ -17,12 +17,8 @@
package org.mitre.uma.model;
import java.util.Collection;
import java.util.Date;
import java.util.Set;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
@ -33,38 +29,19 @@ import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
/**
*
* An UMA permission, used in the protection API.
*
* @author jricher
*
* @author jricher
*/
@Entity
@Table(name = "permission")
@NamedQueries({
@NamedQuery(name = Permission.QUERY_TICKET, query = "select p from Permission p where p.ticket = :" + Permission.PARAM_TICKET)
})
public class Permission {
public static final String QUERY_TICKET = "Permission.queryByTicket";
public static final String PARAM_TICKET = "ticket";
private Long id;
private ResourceSet resourceSet;
private Set<String> scopes;
private String ticket;
private Date expiration;
private Collection<Claim> claimsSupplied;
/**
* @return the id
*/
@ -74,14 +51,14 @@ public class Permission {
public Long getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* @return the resourceSet
*/
@ -117,55 +94,4 @@ public class Permission {
public void setScopes(Set<String> scopes) {
this.scopes = scopes;
}
/**
* @return the ticket
*/
@Basic
@Column(name = "ticket")
public String getTicket() {
return ticket;
}
/**
* @param ticket the ticket to set
*/
public void setTicket(String ticket) {
this.ticket = ticket;
}
/**
* @return the expiration
*/
@Basic
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "expiration")
public Date getExpiration() {
return expiration;
}
/**
* @param expiration the expiration to set
*/
public void setExpiration(Date expiration) {
this.expiration = expiration;
}
/**
* @return the claimsSupplied
*/
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "permission_id")
public Collection<Claim> getClaimsSupplied() {
return claimsSupplied;
}
/**
* @param claimsSupplied the claimsSupplied to set
*/
public void setClaimsSupplied(Collection<Claim> claimsSupplied) {
this.claimsSupplied = claimsSupplied;
}
}
}

View File

@ -0,0 +1,146 @@
/*******************************************************************************
* Copyright 2015 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
*
* 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 org.mitre.uma.model;
import java.util.Collection;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
/**
*
* An UMA permission, used in the protection API.
*
* @author jricher
*
*/
@Entity
@Table(name = "permission_ticket")
@NamedQueries({
@NamedQuery(name = PermissionTicket.QUERY_TICKET, query = "select p from PermissionTicket p where p.ticket = :" + PermissionTicket.PARAM_TICKET)
})
public class PermissionTicket {
public static final String QUERY_TICKET = "PermissionTicket.queryByTicket";
public static final String PARAM_TICKET = "ticket";
private Long id;
private Permission permission;
private String ticket;
private Date expiration;
private Collection<Claim> claimsSupplied;
/**
* @return the id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
public Long getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* @return the permission
*/
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "permission_id")
public Permission getPermission() {
return permission;
}
/**
* @param permission the permission to set
*/
public void setPermission(Permission permission) {
this.permission = permission;
}
/**
* @return the ticket
*/
@Basic
@Column(name = "ticket")
public String getTicket() {
return ticket;
}
/**
* @param ticket the ticket to set
*/
public void setTicket(String ticket) {
this.ticket = ticket;
}
/**
* @return the expiration
*/
@Basic
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "expiration")
public Date getExpiration() {
return expiration;
}
/**
* @param expiration the expiration to set
*/
public void setExpiration(Date expiration) {
this.expiration = expiration;
}
/**
* @return the claimsSupplied
*/
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "permission_ticket_id")
public Collection<Claim> getClaimsSupplied() {
return claimsSupplied;
}
/**
* @param claimsSupplied the claimsSupplied to set
*/
public void setClaimsSupplied(Collection<Claim> claimsSupplied) {
this.claimsSupplied = claimsSupplied;
}
}

View File

@ -17,7 +17,7 @@
package org.mitre.uma.repository;
import org.mitre.uma.model.Permission;
import org.mitre.uma.model.PermissionTicket;
/**
* @author jricher
@ -26,10 +26,13 @@ import org.mitre.uma.model.Permission;
public interface PermissionRepository {
/**
*
* Save a permission ticket.
*
* @param p
* @return
*/
public Permission save(Permission p);
public PermissionTicket save(PermissionTicket p);
/**
* Get the permission indicated by its ticket value.
@ -37,6 +40,6 @@ public interface PermissionRepository {
* @param ticket
* @return
*/
public Permission getByTicket(String ticket);
public PermissionTicket getByTicket(String ticket);
}

View File

@ -19,7 +19,7 @@ package org.mitre.uma.service;
import java.util.Set;
import org.mitre.uma.model.Permission;
import org.mitre.uma.model.PermissionTicket;
import org.mitre.uma.model.ResourceSet;
import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException;
@ -36,7 +36,7 @@ public interface PermissionService {
* @return the created (and stored) permission object, with ticket
* @throws InsufficientScopeException if the scopes in scopes don't match those in resourceSet.getScopes
*/
public Permission create(ResourceSet resourceSet, Set<String> scopes);
public PermissionTicket createTicket(ResourceSet resourceSet, Set<String> scopes);
/**
*
@ -45,6 +45,6 @@ public interface PermissionService {
* @param the ticket value to search on
* @return the permission object, or null if none is found
*/
public Permission getByTicket(String ticket);
public PermissionTicket getByTicket(String ticket);
}

View File

@ -235,11 +235,16 @@ CREATE TABLE IF NOT EXISTS resource_set_scope (
scope VARCHAR(256) NOT NULL
);
CREATE TABLE IF NOT EXISTS permission_ticket (
id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) PRIMARY KEY,
ticket VARCHAR(256) NOT NULL,
permission_id BIGINT NOT NULL,
expiration TIMESTAMP
);
CREATE TABLE IF NOT EXISTS permission (
id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) PRIMARY KEY,
resource_set_id BIGINT NOT NULL,
ticket VARCHAR(256) NOT NULL,
expiration TIMESTAMP
resource_set_id BIGINT NOT NULL
);
CREATE TABLE IF NOT EXISTS permission_scope (
@ -254,7 +259,7 @@ CREATE TABLE IF NOT EXISTS claim (
claim_type VARCHAR(1024),
claim_value VARCHAR(1024),
resource_set_id BIGINT,
permission_id BIGINT
permission_ticket_id BIGINT
);
CREATE TABLE IF NOT EXISTS claim_token_format (

View File

@ -21,7 +21,7 @@ import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import org.mitre.uma.model.Permission;
import org.mitre.uma.model.PermissionTicket;
import org.mitre.uma.repository.PermissionRepository;
import org.mitre.util.jpa.JpaUtil;
import org.springframework.stereotype.Repository;
@ -39,7 +39,7 @@ public class JpaPermissionRepository implements PermissionRepository {
@Override
@Transactional
public Permission save(Permission p) {
public PermissionTicket save(PermissionTicket p) {
return JpaUtil.saveOrUpdate(p.getId(), em, p);
}
@ -47,9 +47,9 @@ public class JpaPermissionRepository implements PermissionRepository {
* @see org.mitre.uma.repository.PermissionRepository#getByTicket(java.lang.String)
*/
@Override
public Permission getByTicket(String ticket) {
TypedQuery<Permission> query = em.createNamedQuery(Permission.QUERY_TICKET, Permission.class);
query.setParameter(Permission.PARAM_TICKET, ticket);
public PermissionTicket getByTicket(String ticket) {
TypedQuery<PermissionTicket> query = em.createNamedQuery(PermissionTicket.QUERY_TICKET, PermissionTicket.class);
query.setParameter(PermissionTicket.PARAM_TICKET, ticket);
return JpaUtil.getSingleResult(query.getResultList());
}

View File

@ -23,6 +23,7 @@ import java.util.UUID;
import org.mitre.oauth2.service.SystemScopeService;
import org.mitre.uma.model.Permission;
import org.mitre.uma.model.PermissionTicket;
import org.mitre.uma.model.ResourceSet;
import org.mitre.uma.repository.PermissionRepository;
import org.mitre.uma.service.PermissionService;
@ -49,7 +50,7 @@ public class DefaultPermissionService implements PermissionService {
* @see org.mitre.uma.service.PermissionService#create(org.mitre.uma.model.ResourceSet, java.util.Set)
*/
@Override
public Permission create(ResourceSet resourceSet, Set<String> scopes) {
public PermissionTicket createTicket(ResourceSet resourceSet, Set<String> scopes) {
// check to ensure that the scopes requested are a subset of those in the resource set
@ -57,13 +58,16 @@ public class DefaultPermissionService implements PermissionService {
throw new InsufficientScopeException("Scopes of resource set are not enough for requested permission.");
}
Permission p = new Permission();
p.setResourceSet(resourceSet);
p.setScopes(scopes);
p.setTicket(UUID.randomUUID().toString());
p.setExpiration(new Date(System.currentTimeMillis() + permissionExpirationSeconds * 1000L));
Permission perm = new Permission();
perm.setResourceSet(resourceSet);
perm.setScopes(scopes);
return repository.save(p);
PermissionTicket ticket = new PermissionTicket();
ticket.setPermission(perm);
ticket.setTicket(UUID.randomUUID().toString());
ticket.setExpiration(new Date(System.currentTimeMillis() + permissionExpirationSeconds * 1000L));
return repository.save(ticket);
}
@ -71,7 +75,7 @@ public class DefaultPermissionService implements PermissionService {
* @see org.mitre.uma.service.PermissionService#getByTicket(java.lang.String)
*/
@Override
public Permission getByTicket(String ticket) {
public PermissionTicket getByTicket(String ticket) {
return repository.getByTicket(ticket);
}

View File

@ -32,7 +32,7 @@ import org.mitre.openid.connect.view.HttpCodeView;
import org.mitre.openid.connect.view.JsonEntityView;
import org.mitre.openid.connect.view.JsonErrorView;
import org.mitre.uma.model.Claim;
import org.mitre.uma.model.Permission;
import org.mitre.uma.model.PermissionTicket;
import org.mitre.uma.model.ResourceSet;
import org.mitre.uma.service.PermissionService;
import org.springframework.beans.factory.annotation.Autowired;
@ -102,15 +102,15 @@ public class AuthorizationRequestEndpoint {
String ticketValue = o.get(TICKET).getAsString();
Permission perm = permissionService.getByTicket(ticketValue);
PermissionTicket ticket = permissionService.getByTicket(ticketValue);
if (perm != null) {
if (ticket != null) {
// found the ticket, see if it's any good
ResourceSet rs = perm.getResourceSet();
ResourceSet rs = ticket.getPermission().getResourceSet();
Collection<Claim> claimsRequired = rs.getClaimsRequired();
Collection<Claim> claimsSupplied = perm.getClaimsSupplied();
Collection<Claim> claimsSupplied = ticket.getClaimsSupplied();
Collection<Claim> claimsUnmatched = new HashSet<>(claimsRequired);

View File

@ -30,7 +30,7 @@ import org.mitre.oauth2.model.SystemScope;
import org.mitre.oauth2.service.SystemScopeService;
import org.mitre.openid.connect.view.JsonEntityView;
import org.mitre.openid.connect.view.JsonErrorView;
import org.mitre.uma.model.Permission;
import org.mitre.uma.model.PermissionTicket;
import org.mitre.uma.model.ResourceSet;
import org.mitre.uma.service.PermissionService;
import org.mitre.uma.service.ResourceSetService;
@ -126,7 +126,7 @@ public class PermissionRegistrationEndpoint {
}
// create the permission
Permission permission = permissionService.create(resourceSet, scopes);
PermissionTicket permission = permissionService.createTicket(resourceSet, scopes);
if (permission != null) {
// we've created the permission, return the ticket

View File

@ -24,7 +24,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mitre.oauth2.service.SystemScopeService;
import org.mitre.uma.model.Permission;
import org.mitre.uma.model.PermissionTicket;
import org.mitre.uma.model.ResourceSet;
import org.mitre.uma.repository.PermissionRepository;
import org.mockito.AdditionalAnswers;
@ -94,7 +94,7 @@ public class TestDefaultPermissionService {
rs2.setScopes(scopes2);
// have the repository just pass the argument through
when(permissionRepository.save(Mockito.any(Permission.class))).then(AdditionalAnswers.returnsFirstArg());
when(permissionRepository.save(Mockito.any(PermissionTicket.class))).then(AdditionalAnswers.returnsFirstArg());
when(scopeService.scopesMatch(anySetOf(String.class), anySetOf(String.class))).then(new Answer<Boolean>() {
@ -114,12 +114,12 @@ public class TestDefaultPermissionService {
/**
* Test method for {@link org.mitre.uma.service.impl.DefaultPermissionService#create(org.mitre.uma.model.ResourceSet, java.util.Set)}.
* Test method for {@link org.mitre.uma.service.impl.DefaultPermissionService#createTicket(org.mitre.uma.model.ResourceSet, java.util.Set)}.
*/
@Test
public void testCreate_ticket() {
Permission perm = permissionService.create(rs1, scopes1);
PermissionTicket perm = permissionService.createTicket(rs1, scopes1);
// we want there to be a non-null ticket
assertNotNull(perm.getTicket());
@ -127,7 +127,7 @@ public class TestDefaultPermissionService {
@Test
public void testCreate_uuid() {
Permission perm = permissionService.create(rs1, scopes1);
PermissionTicket perm = permissionService.createTicket(rs1, scopes1);
// we expect this to be a UUID
UUID uuid = UUID.fromString(perm.getTicket());
@ -139,8 +139,8 @@ public class TestDefaultPermissionService {
@Test
public void testCreate_differentTicketsSameClient() {
Permission perm1 = permissionService.create(rs1, scopes1);
Permission perm2 = permissionService.create(rs1, scopes1);
PermissionTicket perm1 = permissionService.createTicket(rs1, scopes1);
PermissionTicket perm2 = permissionService.createTicket(rs1, scopes1);
assertNotNull(perm1.getTicket());
assertNotNull(perm2.getTicket());
@ -153,8 +153,8 @@ public class TestDefaultPermissionService {
@Test
public void testCreate_differentTicketsDifferentClient() {
Permission perm1 = permissionService.create(rs1, scopes1);
Permission perm2 = permissionService.create(rs2, scopes2);
PermissionTicket perm1 = permissionService.createTicket(rs1, scopes1);
PermissionTicket perm2 = permissionService.createTicket(rs2, scopes2);
assertNotNull(perm1.getTicket());
assertNotNull(perm2.getTicket());
@ -168,7 +168,7 @@ public class TestDefaultPermissionService {
public void testCreate_scopeMismatch() {
@SuppressWarnings("unused")
// try to get scopes outside of what we're allowed to do, this should throw an exception
Permission perm = permissionService.create(rs1, scopes2);
PermissionTicket perm = permissionService.createTicket(rs1, scopes2);
}
}