All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.bdrc.auth.rdf.RdfAuthModel Maven / Gradle / Ivy

There is a newer version: 3.0.0
Show newest version
package io.bdrc.auth.rdf;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Properties;
import java.util.Timer;

import org.apache.jena.query.DatasetAccessor;
import org.apache.jena.query.DatasetAccessorFactory;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.ResIterator;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.rdf.model.Statement;
import org.apache.jena.rdf.model.StmtIterator;
import org.apache.jena.sparql.vocabulary.FOAF;
import org.apache.jena.vocabulary.RDF;
import org.apache.jena.vocabulary.RDFS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.bdrc.auth.AuthProps;
import io.bdrc.auth.model.Application;
import io.bdrc.auth.model.AuthDataModelBuilder;
import io.bdrc.auth.model.Endpoint;
import io.bdrc.auth.model.Group;
import io.bdrc.auth.model.Permission;
import io.bdrc.auth.model.ResourceAccess;
import io.bdrc.auth.model.Role;
import io.bdrc.auth.model.User;

/*******************************************************************************
 * Copyright (c) 2018 Buddhist Digital Resource Center (BDRC)
 *
 * If this file is a derivation of another work the license header will appear
 * below; otherwise, this work is 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.
 ******************************************************************************/

public class RdfAuthModel implements Runnable {

	static Model authMod;
	static HashMap users;
	static HashMap groups;
	static HashMap roles;
	static HashMap> personalAccess;
	static ArrayList anyStatusGroups;
	static ArrayList permissions;
	static ArrayList endpoints;
	static ArrayList access;
	static ArrayList applications;
	static HashMap> paths;
	static Long updated = null;

	private static int PERIOD_MS;
	private static final int DELAY_MS = 5000;
	public final static Logger log = LoggerFactory.getLogger(RdfAuthModel.class.getName());

	// Reads authModel from fuseki and starts a ModelUpdate timer
	public static void init() {
		readAuthModel();
		final ModelUpdate task = new ModelUpdate();
		final Timer timer = new Timer();
		PERIOD_MS = Integer.parseInt(AuthProps.getProperty("updatePeriod"));
		timer.schedule(task, DELAY_MS, PERIOD_MS);
	}

	// Reads authModel from fuseki and starts a ModelUpdate timer
	public static void initForTest(boolean update, boolean isTest) {
		if (update) {
			updateAuthData(null);
		} else {
			readAuthModel();
		}
	}

	public static void initForStaticTests() {
		InputStream stream = Application.class.getClassLoader().getResourceAsStream("rdfAuthTestModel.ttl");
		final Model m = ModelFactory.createDefaultModel();
		m.read(stream, "", "TURTLE");
		resetModel(m);
	}

	public static Long getUpdated() {
		return updated;
	}

	public static void update(final long updatedTime) {
		updated = updatedTime;
	}

	public static Model getFullModel() {
		return authMod;
	}

	public static boolean isSecuredEndpoint(final String appId, final String path) {
		final ArrayList pth = paths.get(appId);
		if (pth != null) {
			return pth.contains(path);
		}
		return false;
	}

	public static HashMap getUsers() {

		if (users != null) {
			return users;
		}
		users = new HashMap();
		final ResIterator it = authMod.listResourcesWithProperty(RDF.type, RdfConstants.USER);
		while (it.hasNext()) {
			final Resource rs = it.next();
			final User user = new User();
			user.setAuthId(rs.getProperty(RdfConstants.AUTHID).getObject().toString());
			user.setName(rs.getProperty(FOAF.name).getObject().toString());
			user.setEmail(rs.getProperty(FOAF.mbox).getObject().toString());
			user.setIsSocial(rs.getProperty(RdfConstants.IS_SOCIAL).getObject().toString());
			final String userId = rs.getURI();
			user.setUserId(getShortName(userId));
			user.setProvider(rs.getProperty(RdfConstants.PROVIDER).getObject().toString());
			user.setConnection(rs.getProperty(RdfConstants.CONNECTION).getObject().toString());
			StmtIterator sit = rs.listProperties(RdfConstants.HAS_ROLE);
			while (sit.hasNext()) {
				final Statement st = sit.next();
				final String role = st.getObject().toString();
				user.getRoles().add(getShortName(role));
			}
			sit = rs.listProperties(RdfConstants.FOR_GROUP);
			while (sit.hasNext()) {
				final Statement st = sit.next();
				final String gp = st.getObject().toString();
				user.getGroups().add(getShortName(gp));
			}
			users.put(getShortName(userId), user);
		}
		return users;
	}

	public static HashMap getGroups() {
		if (groups != null) {
			return groups;
		}
		groups = new HashMap();
		final ResIterator it = authMod.listResourcesWithProperty(RDF.type, RdfConstants.GROUP);
		while (it.hasNext()) {
			final Group gp = new Group();
			final Resource rs = it.next();
			StmtIterator sit = rs.listProperties(RdfConstants.HAS_MEMBER);
			while (sit.hasNext()) {
				final String member = sit.next().getObject().toString();
				gp.getMembers().add(getShortName(member));
			}
			sit = rs.listProperties(RdfConstants.HAS_ROLE);
			while (sit.hasNext()) {
				final String role = sit.next().getObject().toString();
				gp.getRoles().add(getShortName(role));
			}
			gp.setId(getShortName(rs.getURI()));
			gp.setName(rs.getProperty(RDFS.label).getObject().toString());
			gp.setDesc(rs.getProperty(RdfConstants.DESC).getObject().toString());
			groups.put(getShortName(rs.getURI()), gp);
		}
		return groups;
	}

	public static HashMap getRoles() {
		if (roles != null) {
			return roles;
		}
		roles = new HashMap();
		final ResIterator it = authMod.listResourcesWithProperty(RDF.type, RdfConstants.ROLE);
		while (it.hasNext()) {
			final Role role = new Role();
			final Resource rs = it.next();
			StmtIterator sit = rs.listProperties(RdfConstants.HAS_PERMISSION);
			while (sit.hasNext()) {
				role.getPermissions().add(getShortName(sit.next().getObject().toString()));
			}
			role.setId(getShortName(rs.getURI()));
			role.setName(rs.getProperty(RDFS.label).getObject().toString());
			role.setDesc(rs.getProperty(RdfConstants.DESC).getObject().toString());
			final String appId = rs.getProperty(RdfConstants.APPID).getObject().toString();
			role.setAppId(getShortName(appId));
			role.setAppType(rs.getProperty(RdfConstants.APPTYPE).getObject().toString());
			roles.put(getShortName(rs.getURI()), role);
		}
		return roles;
	}

	public static ArrayList getPermissions() {
		if (permissions != null) {
			return permissions;
		}
		permissions = new ArrayList<>();
		final ResIterator it = authMod.listResourcesWithProperty(RDF.type, RdfConstants.PERMISSION);
		while (it.hasNext()) {
			final Permission perm = new Permission();
			final Resource rs = it.next();
			perm.setId(getShortName(rs.getURI()));
			perm.setName(rs.getProperty(RDFS.label).getObject().toString());
			perm.setDesc(rs.getProperty(RdfConstants.DESC).getObject().toString());
			final String appId = rs.getProperty(RdfConstants.APPID).getObject().toString();
			perm.setAppId(getShortName(appId));
			permissions.add(perm);
		}
		return permissions;
	}

	public static ArrayList getPermissions(final ArrayList rls, final ArrayList gps) {
		final ArrayList perm = new ArrayList<>();
		for (final String rl : rls) {
			final Role role = roles.get(rl);
			if (role != null) {
				for (final String p : role.getPermissions()) {
					perm.add(p);
				}
			}
		}
		for (final String rl : rls) {
			final Group gp = groups.get(rl);
			if (gp != null) {
				for (final String p : gp.getRoles()) {
					final Role role = roles.get(p);
					if (role != null) {
						for (final String pp : role.getPermissions()) {
							perm.add(pp);
						}
					}
				}
			}
		}
		return perm;
	}

	public static ArrayList getEndpoints() {
		if (endpoints != null) {
			return endpoints;
		}
		endpoints = new ArrayList<>();
		paths = new HashMap<>();
		final ResIterator it = authMod.listResourcesWithProperty(RDF.type, RdfConstants.ENDPOINT);
		while (it.hasNext()) {
			final Endpoint endp = new Endpoint();
			final Resource rs = it.next();
			StmtIterator sit = rs.listProperties(RdfConstants.FOR_GROUP);
			while (sit.hasNext()) {
				endp.getGroups().add(getShortName(sit.next().getObject().toString()));
			}
			sit = rs.listProperties(RdfConstants.FOR_ROLE);
			while (sit.hasNext()) {
				String role = sit.next().getObject().toString();
				endp.getRoles().add(role.substring(role.lastIndexOf("/") + 1));
			}
			sit = rs.listProperties(RdfConstants.FOR_PERM);
			while (sit.hasNext()) {
				endp.getPermissions().add(getShortName(sit.next().getObject().toString()));
			}
			endp.setPath(rs.getProperty(RdfConstants.PATH).getObject().toString());
			String appId = rs.getProperty(RdfConstants.APPID).getObject().asResource().getLocalName();
			endp.setAppId(appId);
			endpoints.add(endp);
			ArrayList path = paths.get(endp.getAppId());
			if (path == null) {
				path = new ArrayList<>();
			}
			path.add(endp.getPath());
			paths.put(endp.getAppId(), path);
		}
		return endpoints;
	}

	public static ArrayList getResourceAccess() {
		if (access != null) {
			return access;
		}
		access = new ArrayList<>();
		final ResIterator it = authMod.listResourcesWithProperty(RDF.type, RdfConstants.RES_ACCESS);
		while (it.hasNext()) {
			final ResourceAccess acc = new ResourceAccess();
			final Resource rs = it.next();
			acc.setPermission(rs.getProperty(RdfConstants.FOR_PERM).getObject().asResource().getLocalName());
			acc.setPolicy(rs.getProperty(RdfConstants.POLICY).getObject().asResource().getLocalName());
			access.add(acc);
		}
		return access;
	}

	public static HashMap> getPersonalAccess() {
		if (personalAccess != null) {
			return personalAccess;
		}
		personalAccess = new HashMap<>();
		//
		final ResIterator it = authMod.listResourcesWithProperty(RdfConstants.PERSONAL_ACCESS);
		while (it.hasNext()) {
			final Resource rs = it.next();
			String user = rs.getURI();
			String res = rs.getProperty(RdfConstants.PERSONAL_ACCESS).getObject().asResource().getURI();
			ArrayList access = personalAccess.get(user);
			if (access == null) {
				access = new ArrayList<>();
			}
			access.add(res);
			personalAccess.put(user, access);
		}
		return personalAccess;
	}

	public static ArrayList getAnyStatusGroup() {
		if (anyStatusGroups != null) {
			return anyStatusGroups;
		}
		anyStatusGroups = new ArrayList<>();
		final ResIterator it = authMod.listResourcesWithProperty(RdfConstants.ANY_STATUS);
		while (it.hasNext()) {
			final Resource rs = it.next();
			String group = rs.getURI();
			boolean acc = rs.getProperty(RdfConstants.ANY_STATUS).getBoolean();
			if (acc) {
				anyStatusGroups.add(group);
			}
		}
		return anyStatusGroups;
	}

	public static ArrayList getPersonalAccess(String userUri) {
		if (personalAccess != null) {
			return personalAccess.get(userUri);
		}
		return null;
	}

	public static ArrayList getApplications() {
		if (applications != null) {
			return applications;
		}
		applications = new ArrayList<>();
		final ResIterator it = authMod.listResourcesWithProperty(RDF.type, RdfConstants.APPLICATION);
		while (it.hasNext()) {
			final Resource rs = it.next();
			final Application app = new Application();
			app.setName(rs.getProperty(RDFS.label).getObject().toString());
			app.setAppId(getShortName(rs.getURI()));
			app.setAppType(rs.getProperty(RdfConstants.APPTYPE).getObject().toString());
			app.setDesc(rs.getProperty(RdfConstants.DESC).getObject().toString());
			applications.add(app);
		}
		return applications;
	}

	public static User getUser(final String userId) {
		return users.get(userId);
	}

	public static HashMap> getPaths() {
		return paths;
	}

	public static Endpoint getEndpoint(final String path) {
		for (final Endpoint e : endpoints) {
			if (e.getPath().equals(path)) {
				return e;
			}
		}
		return null;
	}

	public static ResourceAccess getResourceAccess(final String accessType) {
		if (access == null) {
			access = getResourceAccess();
		}
		for (final ResourceAccess acc : access) {
			final String policy = acc.getPolicy();
			if (policy.equals(accessType)) {
				return acc;
			}
		}
		return null;
	}

	// Loads the model from fuseki -
	// Used by any application using bdrc-auth-lib
	// The model will then be updated (by ModelUpdate timer)
	// each when a new version has been created and published
	// by the server (ldspdi) receiving callbacks from auth0 or bdrc-auth-lib repo
	public static void readAuthModel() {
		String fusekiUrl = AuthProps.getProperty("fusekiUrl");
		fusekiUrl = fusekiUrl.substring(0, fusekiUrl.lastIndexOf("/"));
		final DatasetAccessor access = DatasetAccessorFactory.createHTTP(fusekiUrl);
		final Model m = access.getModel(AuthProps.getProperty("authDataGraph"));
		if (m != null) {
			resetModel(m);
			update(System.currentTimeMillis());
		}
	}

	static void resetModel(final Model m) {
		authMod = m;
		getUsers();
		getGroups();
		getRoles();
		getPermissions();
		getEndpoints();
		getApplications();
		getResourceAccess();
		getPersonalAccess();
		getAnyStatusGroup();
		update(System.currentTimeMillis());
	}

	// Reloads and reset the model from auth0 and bdrc-auth-lib policies.ttl
	// This MUST BE used at startup by the server implementing webhooks callbacks
	// and each time a callback to that server is triggerred.
	// a new update time is then set by resetModel().
	public static void updateAuthData(String fusekiUrl) {
		if (fusekiUrl == null) {
			fusekiUrl = AuthProps.getProperty("fusekiUrl");
		}
		fusekiUrl = fusekiUrl.substring(0, fusekiUrl.lastIndexOf("/"));
		log.info("Service fuseki >> " + fusekiUrl);
		log.info("authDataGraph >> " + AuthProps.getProperty("authDataGraph"));
		final DatasetAccessor access = DatasetAccessorFactory.createHTTP(fusekiUrl);
		try {
			final AuthDataModelBuilder auth = new AuthDataModelBuilder();
			access.putModel(AuthProps.getProperty("authDataGraph"), auth.getModel());
			resetModel(auth.getModel());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static String getShortName(String st) {
		return st.substring(st.lastIndexOf("/") + 1);
	}

	@Override
	public void run() {
		try {
			updateAuthData(null);
		} catch (Exception e) {
			log.error("Running error", e);
		}
		log.info("Done loading and updating rdfAuth Model");
	}

	public static void main(String[] args) {
		Properties props = new Properties();

		AuthProps.init(props);
		Thread t = new Thread(new RdfAuthModel());
		t.start();
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy